Java多线程编程总结笔记——01 Java语言的线程

比较花费时间的I/O操作#

多个客户端#

基本上网络上的服务器必须同时处理一个以上的客户端,不过,一定要在服务器这边的程序设计加入一个以上客户端的概念的话,程序会变得更复杂。此时,不妨准备一个当有客户端连接到服务器的时候,会自动出来迎接这个客户点的线程,这样一来,服务器的程序就可以设计成好像只服务一个客户端

并发与并行#

当有一个以上的线程的线程来操作时,若计算机只有一个中央处理器,根本不可能进行一个以上的处理。

如果在有一个以上的中央处理器的计算机上跑程序,则线程的程序可能是并行(parallel)而非并发,就可以同时运行一个以上的处理。

GUI应用程序#

几乎所有的GUI应用程序都会用多线程。举例来说加入现在有人在用word编辑一个比较大的文本文件刚刚才做过单字“查找”操作,当word进行查找时,屏幕上会出现“停止查找按钮”,用户可以随时停止查找。这个功能其实就用到了多线程。

(1)执行查找

(2)显示按钮,若按钮按下则停止查找

这两个操作分别交给不同的线程进行。这样一来执行线程(1)的线程可以专心查找,执行(2)的线程也可专心在GUI操作上,程序就会变得比较简单。

线程的启动#

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
54
55
56
57
58
59
60
61
62
/**
* @Title: Thread1.java
* @Package: org.lenvon.thread
* @Description: TODO
* @author: Lenvon
* @date: 2015年6月17日 下午3:06:51
* @version: V1.0
*/
package org.lenvon.thread;

/**
* @moudle: Thread1
* @version:v1.0
* @Description: TODO
* @author: Lenvon
* @date: 2015年6月17日 下午3:06:51
*
*/
public class Thread01 {

static class PrintThread extends Thread {
private String msg ;

/**
* <p>Title: </p>
* <p>Description: </p>
* @param msg
*/
public PrintThread(String msg) {
this.msg = msg;
}

/**
*
* <p>Title: run</p>
* <p>author : Lenvon</p>
* <p>date : 2015年6月17日 下午3:08:40</p>
*/
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(msg);
}

}

/**
*
* <p>Title: main</p>
* <p>author : Lenvon</p>
* <p>date : 2015年6月17日 下午3:06:51</p>
*
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new PrintThread("Good").start();
new PrintThread("Nice").start();
System.out.println("End---------------");
}

}

“PrintThread的实例”和“线程本身”是两个不同的部分,即使建立了“PrintThread的实例”,也还没有启动线程,而且就算线程已经结束,PrintThread的实例也不会就这样消失不见。别忘了,在字符串输出结束之前,已经启动的两个线程还活着,一直要等到所有线程都已经结束,程序才会结束。当所有线程都结束,这个程序才会正式结束。

Thread类和Runnable接口#

Thread类也实现了Runnable 接口,也有run()方法,只不过Thread类的run()方法的主体是空的没有执行任何部分。Thread类的run()方法通常是被子类覆盖(override)

Synchronized实例方法和Synchronized阻挡#

假设现在有一个类型如下的synchronized实例方法

1
2
3
4
5
synchronized void method(){



}

在功能上和下面以synchronized阻挡为主的方法有异曲同工之妙。

1
2
3
4
5
6
7
8
9
void method(){

Synchronized(this){



}

}

换句话说synchronized方法是使用this锁去做线程的共享互斥。

Synchronized类方法和Synchronized阻挡#

假设现在有一个类型如下的synchronized的类方法,synchronized类方法有限制同时只能让一个线程执行。这部分和synchronized实例方法一样,但是两者是有不同的。

1
2
3
4
5
6
7
    static synchronized voidmethod(){



}

}

换句话说synchronized的类方法是使用该类的类对象的锁去做线程的共享互斥。Something.class是对应Something类的java.lang.Class类的实例。

Wait方法——把线程放入wait set#

使用wait方法时,线程便进入wait set,假设现在已经执行如下语句:obj.wait();

则目前的线程停止执行,进入实例obj的的wait set.这个操作成为:线程在obj上wait.

如果实例方法还有如下的语句时:wait();

则其意义同:this.wait();

故执行wait的线程就会进入this的wait set.此时就变成了在this上wait.

如欲执行wait()方法,线程需获取锁定(这是规则)。但是当线程进入wait set时,已经释放了该实例的锁定。

Notify方法——从wait set拿出线程#

使用notify()(通知)方法时,可以从wait set拿出一个线程。

obj.notify();则从wait set里的线程中挑出一个,唤醒这个线程。被唤醒的线程便退wait set

Notify后的线程#

被notify唤醒的线程不是在notify后立即执行,因为在notify的那一刻,执行notify 的线程还握着锁定不放,所以其他线程无法获取该实例的锁定。

Notify如何选择线程#

假设执行notify方法时,wait set里面正在执行的线程不止一个。规格并没有注明此时该选择哪一个线程。究竟是选择等待线程里面的第一个,随机选择或是另以其他方式选择,则以java处理系统而异。所以在写程序时,程序属性最好不要写成会因所选线程而有所变动。

notifyAll()方法——从wait set 拿出所有线程

使用notifyAll(通知全体)方法时,会将所有在waitset苦等的线程都拿出来。

obj.notifyAll()则会唤醒所有留在实例obj的wait set里的线程。

而notifyAll();则其意义同this.notifyAll();故这个语句所在方法的实例(this)的wait set里的线程会全部放出来。

跟wait方法和notify方法一样,线程必须要获取要调用实例的锁定,才能调用notifyAll方法。

被唤醒的线程便开始去获取刚才wait时释放掉的锁定,那么现在这个锁定现在是在谁的手中呢?没错,锁定就是在刚才执行notifyAll方法的程序手里,因此即使所有线程都退出了wait set,但他们仍然在去获得锁定的状态下,还是有阻挡。要等到刚才执行notifyAll方法的线程释放出锁定后,其中一名幸运儿才会实际执行。

要是没有锁定呢#

若没有锁定的线程去调用wait,notify或notifyAll时,便会抛出异常java.lang.IllegalMonitorStateException.

调用notify方法还是notifyAll方法#

Notify方法和notifyAll方法两者非常相似,到底该用哪一个?老实说,这个选择有点难。选择notify的话,因为要唤醒的线程比较少,程序处理速度当然要比notifyAll略胜一筹。但是选择notify时,若这部分程序处理的不好,可能会有程序挂掉的危险性,一般说来,选择notifyAll所写出来的程序代码要比选择notify可靠。除非你能确定程序员对程序代码的意义和能力限度一清二楚,否则选择notifyAll应该比较稳扎稳打。

------------ 本 文 结 束 感 谢 您 的 阅 读 ------------
坚持技术分享, 您的支持将鼓励我继续创作!
  • 本文标题: Java多线程编程总结笔记——01 Java语言的线程
  • 本文作者: Lenvon
  • 发布时间: 2019年12月04日 - 16:55:48
  • 最后更新: 2019年12月30日 - 00:13:12
  • 本文链接: https://lenvon2012.github.io/2019/12/04/java-multi-thread-01/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!