1.多线程之间通讯
多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同。
//共享资源实体类
class Person {
private String name;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
//线程一
class T1 implements Runnable {
private Person p;
public T1(Person p) {
this.p = p;
}
public void run() {
boolean b = true;
while(true) {
synchronized (p) {
if(b) {
p.setName("wenlong");
p.setSex("男");
b = false;
}else {
p.setName("bug");
p.setSex("男");
b = true;
}
}
}
}
}
//线程二
class T2 implements Runnable {
private Person p;
public T2(Person p) {
this.p = p;
}
public void run() {
while(true) {
synchronized (p) {
System.out.println(p.getName() + p.getSex());
}
}
}
}
//主函数
public class ThreadDemo {
public static void main(String[] args) {
Person p = new Person();
Thread tt = new Thread(new T1(p));
Thread ttt = new Thread(new T2(p));
tt.start();
ttt.start();
}
}
//运行结果
wenlong男
wenlong男
wenlong男
wenlong男
wenlong男
wenlong男
wenlong男
wenlong男
bug男
bug男
bug男
bug男
bug男
bug男
wait(),notify,notifyAll()方法
wait(),notify(),notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态。
这个方法最终调用的都是jvm级的natie方法,随着jvm运行平台的不同可能有些许差异。
如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。
如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。
如果对象调用了notifyall方法就会通知所有等待这个对象控制权的线程继续运行。
注意:一定要在线程同步中使用,并且是同一个锁的资源。
public class ThreadDemo {
public static void main(String[] args) {
Person p = new Person();
Thread tt = new Thread(new T1(p));
Thread ttt = new Thread(new T2(p));
tt.start();
ttt.start();
}
}
class Person {
private String name;
private String sex;
private boolean bool = false;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public boolean isBool() {
return bool;
}
public void setBool(boolean bool) {
this.bool = bool;
}
}
class T1 implements Runnable {
private Person p;
public T1(Person p) {
this.p = p;
}
public void run() {
boolean b = true;
while(true) {
synchronized (p) {
if(p.isBool()) {
try {
p.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(b) {
p.setName("wenlong");
p.setSex("男");
b = false;
}else {
p.setName("bug");
p.setSex("男");
b = true;
}
p.setBool(true);
p.notify();
}
}
}
}
class T2 implements Runnable {
private Person p;
public T2(Person p) {
this.p = p;
}
public void run() {
while(true) {
synchronized (p) {
if(!p.isBool()) {
try {
p.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(p.getName() + p.getSex());
p.setBool(false);
p.notify();
}
}
}
}
//运行结果
bug男
wenlong男
bug男
wenlong男
bug男
wenlong男
bug男
wenlong男
bug男
wenlong男
wait与sleep区别
sleep方法是属于Thread类中的,而wait()方法,则是属于object类中的
sleep()方法导致了程序暂停指定的时间,让出cpu该其他线程,但是他的监控状态依然保持着,当指定的时间到了又会自动恢复运行状态。在调用sleep()方法的时候,线程不会释放对象锁。
而调用wait方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备
JDK1.5-Lock
在 jdk1.5 之后,并发包中新增了 Lock 接口(以及相关实现类)用来实现锁功能,Lock 接口提供了与 synchronized 关键字类似的同步功能,但需要在使用时手动获取锁和释放锁。
Lock lock = new ReentrantLock();
lock.lock();
try{
//可能会出现线程安全的操作
}finally{
//一定在finally中释放锁
//也不能把获取锁在try中进行,因为有可能在获取锁的时候抛出异常
lock.ublock();
}
Lock接口与synchronized关键字的区别
Lock接口可以尝试非阻塞地获取锁 当前线程尝试获取锁。如果这一时刻锁没有被其他线程获取到,则成功获取并持有锁。
Lock接口能被中断地获取锁与synchronized不同,获取到锁的线程能够响应中断,当获取到的锁的线程被中断时,中断异常将会被抛出,同时锁会被释放。
Lock接口在指定的截止时间之前获取锁,如果截止时间到了依旧无法获取锁,则返回。
condition用法
condition的功能类似于在传统的线程技术中的Object.wait()和Object.notify()的功能
Condition condition = lock.newCondition();
condition.await();
condition.signal()
ThreadLoca
threadLocal提高一个线程的局部变量,访问某个线程拥有自己局部变量。
当使用ThreadLocal维护变量时,ThreadLocal为每个使用变量的线程提供独立的变量副本,所有每一线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。
ThreadLoca实现原理
ThreadLoca通过map集合
map.put("当前线程",值);