java多线程(二)

异步和同步

使用多线程不可避免的就是同步和异步的问题:
异步:就是开多个线程,然后同时执行各自的业务逻辑,这样使用可以让程序更加高效率的执行任务,相当于可以一边听歌一边写文档。(但是在系统内部线程执行的还是串行,只是我们视觉上察觉不到,所以宏观上是并发的)
同步:在我们写多线程代码时,有些时候我们需要让一个线程等待另一个线程执行完成后再继续执行,按照顺序执行线程,这样是为了保证异步带来的数据不正确问题(线程安全问题)。

异步

异步就是我们开了另一个线程,那个时候就是在异步执行代码了

1
2
3
4
5
6
new Thread(new Runnable(){
@Override
public void run() {
//要执行的方法
}
});

同步

普通的同步就是我们没有考虑全局变量和线程共享资源的情况下我们,就用线程Thread类join方法或者是sleep方法。
join方法是让调用的线程等待被调用的线程执行完毕后才继续执行。(注意调用的顺序,还有join方法调用要在线程类需要的方法里面去调用,如果是在建立对象后调用是无效的)
sleep是让线程等待的方法,里面的参数是时间,以毫秒为单位(wait方法也是让线程等待进入休眠状态,后面会将两者的区别)

1
2
3
4
5
6
7
8
9
public static void main(String[] args) throws InterruptedException {
Test1 test = new Test1();
Thread t1 = new Thread(test,"窗口1");
t1.start();
//这里执行join方法后,主线程会等待t1线程执行结束后才继续执行后面的代码
t1.join();
//Thread.sleep(1000);这个是主线程休眠1秒后自动唤醒
System.out.println("执行完毕");
}

如果把join方法放在start方法后面,那么其实join方法没有用,线程没有同步,依然是异步的。

join方法源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public final void join() throws InterruptedException {

join(0);

}

public final synchronized void join(long millis)

throws InterruptedException {

long base = System.currentTimeMillis();

long now = 0;



if (millis < 0) {

throw new IllegalArgumentException("timeout value is negative");

}



if (millis == 0) {

while (isAlive()) {

wait(0);

}

} else {

while (isAlive()) {

long delay = millis - now;

if (delay <= 0) {

break;

}

wait(delay);

now = System.currentTimeMillis() - base;

}

}

}

这个我们可以看出join方法是无法别子类继承改写的方法(final修饰),方法做了判断时间是否正确,负的抛出异常,其实代码也是调用了wait的方法。