用于表示多个操作“依次处理”。比如把十个操作交给一个人来处理时,这个人要一个一个地按顺序来处理
并行
用于标识多个操作“同时处理”。比如十个操作分给两个人处理时,这两个人就会并行来处理。
并发
相对于顺序和并行来说比较抽象,用于表示“将一个操作分割成多个部分并且允许无序处理”。比如将十个操作分成相对独立的两类,这样便能够开始并发处理了。如果一个人来处理,这个人就是顺序处理分开的并发操作,而如果是两个人,这两个人就可以并行处理同一个操作。
总结
多线程程序都是并发处理的。如果CPU只有一个,那么并发处理就是顺序执行的,而如果有多个CPU,那么并发处理就可能会并行运行。
并发处理的顺序执行与并发处理的并行执行示意图如下所示
线程启动与中止
启动方式
Thread
Runnable
以上两种方式都需要使用start方法用于启动新的线程,在此需要注意的事情是,启动新线程调用的是start方法而不是run方法
终止
直到所有的线程都终止后,程序才会终止。也就是说,当这两个线程都终止后,程序才会终止。
Java程序的终止是指除守护线程以外的线程全部终止。守护线程是执行后台作业的线程。我们可以通过setDaemon方法把线程设置为守护线程。
小知识
java.util.concurrent包中包含一个将线程创建抽象化的ThreadFactory接口。利用该接口,我们可以将Runnable作为传入参数并通过new创建Thread实例的处理隐藏在ThreadFactory内部。
Executors类中含有多种创建ThreadFactory的方法,感兴趣的可以去看一下源码
synchronized相关
synchronized方法
如果声明一个方法时,在前面加上关键字synchronized那么这个方法就只能由一个线程运行。只能由一个线程运行是每次只能由一个线程运行的意思,并不是说仅能让某一特定线程运行。这种方法叫做synchronized,有时也称为同步方法。
synchronizedvoidmethod(){
...
}
复制代码
synchronized代码块
如果只是想让方法中的某一部分由一个线程运行,而非整个方法,则可使用synchronized代码块
synchronized(表达式){
...
}
复制代码
synchronized实例方法和synchronized代码块
假设有如下synchronized实例方法
synchronizedvoidmethod(){
...
}
复制代码
这跟下面将方法体用synchronized代码块包围起来是等效的
voidmethod(){
synchronized(this){
...
}
}
复制代码
synchronized实例方法是使用this的锁来执行线程的互斥处理的
synchronized静态方法和synchronized代码块
synchronized静态方法和synchronized实例方法是相同的。但是synchronized静态方法使用的锁和synchronized实例方法使用的锁是不一样的
classSomething{
staticsynchronizedvoidmethod(){
...
}
}
复制代码
这跟下面将方法体用synchronized代码块包围起来是等效的
classSomething{
staticvoidmethod(){
synchronized(Something.class){
...
}
}
}
复制代码
synchronized静态方法是使用该类的类对象锁来执行线程的互斥处理的。Something.class是Something类对应的java.lang.class类的实例
wait、notify和notifyAll
等待队列
所有实例都拥有一个等待队列,它是在实例的wait方法执行后停止操作的线程队列。就好比为每个实例准备的线程休息室
在执行wait方法后,线程便会暂停操作,(获取相关资料加群:874811168)进入等待队列这个休息室。除非发生下列某一情况,否则线程会一直在等待队列中休眠。
有其他线程的notify方法来唤醒线程
有其他线程的notifyAll方法来唤醒线程
有其他线程的interrupt方法来唤醒线程
wait方法超时
若要执行wait方法,线程必须持有锁。但如果线程进入等待队列,便会释放其实例的锁
notify方法
该方法会将等待队列中的一个线程去除。同wait方法一样,若要执行notify方法,线程也必须持有要调用的实例的锁。
notify唤醒的线程并不会在执行notify的一瞬间就重新运行。因为在执行notify的那一瞬间,执行notify的线程还持有着锁,所以其他线程还无法获取这个实例的锁
notifyAll方法
notify方法仅唤醒一个线程,而notifyAll则唤醒所有线程,这是两者之间唯一的区别
同wait方法和notify方法一样,notifyAll方法也只能由持有要调用的实例锁的线程调用
notify和notifyAll选择
notify方法和notifyAll方法非常相似,到底该使用哪个?
实际上,这很难选择,由于notify唤醒的线程较少,所以处理速度要比使用notifyAll时快。但使用notify时,如果处理不好,程序便可能会停止。一般来说,使用notifyAll时的代码要比使用notify时的更为健壮。
以上就是长沙中公优就业java培训机构的小编针对“Java基础学习:java多线程设计模式教程”的内容进行的回答,希望对大家有所帮助,如有疑问,请在线咨询,有专业老师随时为你服务。