#近期学习JAVA打卡!
接着上次这几天把多线程差不多看完了,当然也手敲了一遍!
上次学会了创建多线程的两种方式,多线程中Thread类的很多方法
这次学的是:1解决线程安全问题的三种方法
2实现死锁
3线程通信
首先是第一个 解决线程安全的三种方法(也可以说是两种);
方式一:同步代码快
synchronized(同步监视器){
//需要被同步的代码块
}
说明 1.操作共享数据的代码,即为需要被同步的代码 //不能太多也不能太少
2.共享数据:多个线程共同操作的变量 //比如下面的ticket
3.同步监视器 俗称:锁 任何一个类的对象都可以充当 //多个线程公用一把锁
方式二:同步方法
5 同步的方式 解决了线程的安全问题—————好处
操作同步代码时,只能有一个线程参与其他线程等待,相当于是一个单线程过程,效率低
方法三:
使用LOCK锁来解决线程的安全问题 JDK5.0新增
1面试题:synchronized和Lock有什么异同
相同点:都可以解决线程安全问题。
不同点:synchronized机制在执行完相应同步代码以后自动关闭
Lock需要手动启动同步(lock()),手动关闭同步(unlock())
2优先使用顺序
Lock→同步代码快(已经进入了方法体,分配了相应资源)→同步方法(在同步代码外)
然后!!!!
是死锁 实现了死锁
1死锁的理解:不同的线程分别占用对方需要的同步资源不放弃
都在等待对方放弃自己需要的同步资源,形成了死锁
2说明:
1)死锁后,不会出现异常,不会出现提示,只是所有的线程处于阻塞状态,无法继续
2)使用同步时,要避免死锁
package com.lrq.threads;
/*死锁
*
* 1死锁的理解:不同的线程分别占用对方需要的同步资源不放弃
* 都在等待对方放弃自己需要的同步资源,形成了死锁
*
* 2说明:
* 1)死锁后,不会出现异常,不会出现提示,只是所有的线程处于阻塞状态,无法继续
* 2)使用同步时,要避免死锁
*
*/
public class DeadLock {
public static void main(String[] args) {
StringBuffer a1=new StringBuffer();
StringBuffer a2=new StringBuffer();
StringBuffer a3=new StringBuffer();
new Thread() {
@Override
public void run() {
synchronized(a1) {
a1.append("L");
a2.append("1");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(a2) {
a1.append("R");
a2.append("2");
}
System.out.println(a1);
System.out.println(a2);
}
}
}.start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized(a2) {
a1.append("Q");
a2.append("3");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(a1) {
a1.append("S");
a2.append("4");
}
System.out.println(a1);
System.out.println(a2);
}
}
}).start();
}}
第三个 线程的通信
线程通信的例子:使用两个线程打印1-100, 线程1,线程2交替打印
*涉及到的三个方法:
*wait()一旦执行,线程就进入阻塞状态,并且释放同步监视器
*notify()一旦执行,就会释放被wait()的一个线程,如果有多个线程就释放优先级高的
*notifyall()一旦执行,释放所有被wait()的线程
*
- wait() notify() notifyall()三个方法必须使用在同步代码快或同步方法中
- wait() notify() notifyall()三个方法的调用者必须是同步代码快或同步方法的同步监视器
-
否则会出现IllegalMonitorStateException
- wait() notify() notifyall()三个方法定义在java.lang.Object类中
- 面试题:wait()和sleep()的异同
- 1.相同点:都可以调用使线程变成阻塞状态
- 2.不同的:1)两个方法声明的位置不同:Thread类中声明sleep(),Object类中声明wait()
-
2)调用的要求不同:sleep()可以在任何需要的场景下调用,wait()只能在同步代码快中调用
-
3)关于是否释放同步监视器:如果两个方法都使用在同步代码快和同步方法中,sleep()不会释放锁 wait()会释放锁
class Number implements Runnable{
private int number=1;
private Object Obj =new Object();
@Override
public void run() {
while(true) {
synchronized(Obj) {
Obj.notify();
if(number<=100) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+number);
number++;
try {
//调用wait使线程进入阻塞状态 然后去释放另外一个线程
Obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else {
break;
}
}
}
}
}
public class communicationTest {
public static void main(String[] args) {
Number N =new Number();
Thread T1 =new Thread(N);
Thread T2 =new Thread(N);
T1.setName("线程一");
T2.setName("线程二");
T1.start();
T2.start();
}
}