p592-599
线程
用户线程和守护线程
1.用户线程:也叫工作线程,当线程的任务执行完或通知方式结束
2守护线程:一般是为工作线程服务的,当所有的用户线选束,守护线程自动结束
3.常见的守护线程:垃圾回收机制
当我们希望当main线程结束后,子线程自动结束,那我们只用将子线程设置为守护线程即可。
线程的生命周期
线程同步机制
1.在多线程编程,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任何同一时刻,最多有一个线程访问,以保证数据的完整性。
2.也可以这里理解:线程同步,即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作。
Synchronized关键字
同步具体方法-Synchronized
1.同步代码块
synchronized(对象){//得到对象的锁,才能操作同步代码
需要被同步代码;
2. synchronized还可以放在方法上,表示整个方法为同步方法
public synchronized void m (String name){
//需要被同步的代码
}
3.如何理解:
就好像某小伙伴上厕所前先把门关上(上锁).完事后再出来(解锁).那么其它小伙伴就可在使用厕所了
4.使用synchronized解决售票问题
package com.day29;
import org.omg.PortableServer.THREAD_POLICY_ID;
public class Day29 {
public static void main(String[] args) {
T t = new T();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
}
class T implements Runnable{
private static int tick = 100;
private boolean loop = true;//控制run的死循环
public synchronized void sell(){//用synchronized上锁
if(tick<=0){
System.out.println("票卖完了。");
loop=false;
return;
}
System.out.println(Thread.currentThread().getName()+
"窗口售出一张,还有"
+--tick+"张。");
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while(loop){
sell();
}
}
}
同步的原理
synchronized是一把锁,当多个线程进入时就会争夺这把锁,执行完后放回锁。
互斥锁
1.Java在Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。
2.每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。
3.关键字synchronized来与对象的互斥锁联系。当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问。
4.同步的局限性:导致程序的执行效率要降低
5.同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一个对象)
6.同步方法(静态的)的锁为当前类本身。
1.同步方法如果没有使用static修饰:默认锁对象为this
2.如果方法使用static修饰,默认锁对象:当前类.class
3.实现的落地步骤;
需要先分析上锁的代码选择同步代码块或同步方法
要求多个线程的锁对象为同一个即可!
线程死锁
多个线程都占用了对方的锁资源,但不肯相让,导致了死锁,在编程是一定要避免死锁的发生.
释放锁
下面操作会释放锁
1.当前线程的同步方法、同步代码块执行结束案例:上厕所,完事出来
2.当前线程在同步代码块、同步方法中遇到break、return.案例:没有正常的完事,经理叫他修改bug,不得已出来
3.当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致异常结束案例:没有正常的完事,发现忘带纸,不得已出来
4.当前线程在同步代码块、同步方法中执行了线程对象的wait()方法,当前线程暂停,并释
放锁。
案例:没有正常完事,觉得需要酝酿下,所以出来等会再进去
下面操作不会释放锁
1.线程执行同步代码块或同步方法时,程序调用Thread.sleep)、Thread.yield(方
法暂停当前线程的执行,不会释放锁
案例:上厕所,太困了,在坑位上眯了一会
2.线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,
该线程不会释放锁。
提示:应尽量避免使用suspend()和resume()来控制线程,方法不再推荐使用