使用多线程可以提高程序运行,使用不好可能会让程序存在很多bug。
在java中实现多线程有两个方法,一个是继承Thread类 ,另一是实现Runnable接口。一般鼓励使用第二种方法。
(适合多个相同的程序代码的线程去处理同一个资源;可以避免java中的单继承的限制;增加程序的健壮性,可以被多个线程共享,代码和数据独立。)
然后调用start方法开启线程。注意:start()方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行是由操作系统决定的。
线程使用过程中,通常要考虑不同线程之间的数据同步和防止死锁的问题。当两个或多个线程之间同时等待对方释放资源的时候就会形成线程之间的死锁。为了防止死锁的发生,需要通过同步来实现线程安全。java中使用关键字 synchronized。
很多面试题会问到线程和进程的区别,在这简单总结下:
1、进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。它不只是程序的代码,还包括当前的活动,通过程序计数器的值和处理寄存器的内容来表示。
2、进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体,我们称其为进程。
3、线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
4、通常在一个进程中可以包含若干个线程,它们可以利用进程所拥有的资源。
5、进程可以独享数据空间,但线程必须共享数据空间。
多线程的同步和异步的区别:
一个进程启动的多个不相干的线程,它们之间的关系为异步。异步机制有临界区、互斥量、信号量、事件这四种方式。
同步:一个资源,当a线程正在使用时,因为同步机制存在,b线程就无法访问该资源。
异步:一个资源,当a线程正在使用时,以为没有同步机制存在,b线程可以访问该资源。
因此,可总结出同步是线程安全的,异步是线程不安全的,容易造成死锁。
以下是对对线程的几个测试代码:
public class Test {
public static void main(String[] args) {
final Data data = new Data();
// new Thread(new add(data)).start();
// new Thread(new dec(data)).start();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
data.dec();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
data.add();
}
}).start();
}
static class Data {
int n = 100;
public synchronized void add() {
n++;
System.out.println(Thread.currentThread().getName() + ":" + n);
}
public synchronized void dec() {
n--;
System.out.println(Thread.currentThread().getName() + ":" + n);
}
}
static class add implements Runnable {
private Data data;
public add(Data data) {
this.data = data;
}
@Override
public void run() {
data.add();
}
}
static class dec implements Runnable {
private Data data;
public dec(Data data) {
this.data = data;
}
@Override
public void run() {
data.dec();
}
}
}
第二个:
public class Test1 {
static int n = 100;
public static void main(String[] args) {
new Thread(new add()).start();
new Thread(new dec()).start();
}
public synchronized static void add() {
n++;
System.out.println(Thread.currentThread().getName() + ":" + n);
}
public synchronized static void dec() {
n--;
System.out.println(Thread.currentThread().getName() + ":" + n);
}
static class add implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
add();
}
}
static class dec implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
dec();
}
}
}