Java架构学习(三)多线程之间的通讯:wait&notify&JDK1.5里面的Lock锁&停止线程&ThreaLocal使用

1、什么是多线程之间的通讯?

多个线程对同一个资源(共享资源),每个线程对共享资源做的动作不同。操作不同。
多线程通讯的生产者与消费者。消息中间件。

如图

这里写图片描述

2、wait的作用?notify作用?

wait的作用: 是让当前线程从运行状态变为休眠状态,释放锁资源

notify:    是让当前线程从休眠状态变为运行状态。唤醒线程。

注意:wait和notify只有在同步的时候才能使用,如在synchronized代码块中使用,而且都是锁来调用的,并且用的是同一个锁。

3、多线程对共享资源写操作有安全问题,一读一写怎么会有安全问题?

解决方法:首先,两个线程都需要进行同步。

生产者线程生产一个,消费者立马消费,
生产者没有任何生产,消费者就不能做读操作。
消费者,没有消费完,生产者就不能继续生产。

这里就是要使用 wait 方法和notify方法。

注意:可见性不具备原子性,线程不安全。

图示

这里写图片描述

4、多线程之间实现同步或通讯的话使用什么?

使用synchronized 和wait 来实现,wait和notify是一起用的,


notifyAll()是唤醒所有等待的线程。

wait 和 notify只能在synchronized中使用才能有通讯功能。

5、sleep和wait的区别?

wait:  是用于同步中可以释放锁的资源,wait需要notify才能从休眠状态变成运行状态。

sleep: 不会释放锁的资源。时间到期从休眠状态变为运行状态。

相同点都是:休眠线程。

以上记录Java多线程之间的通讯基础基本完毕

6、synchronized分析

synchronized(res){
}

Synchronized:什么时候上锁?  答:在代码块开始上锁
synchronized:什么时候释放锁? 答:在代码块结束

synchronized称为内置锁,自动化。

缺点:效率低、扩展不高,不能自定义。

7、JDK1.5 并非包里面的lock锁

并发包:3-5年面试问

并发包里面的Lock锁,保证线程安全问题。

lock锁与synchronized同步锁,有什么区别?

lock:手动上锁,手动释放锁,灵活性高。

多线程并发与网站并发?

多线程并发操作同一个资源
网站并发,多个请求操作同一个资源。

8、lock锁是接口和synchronized关键字区别?

lock锁:可以尝试非阻塞地获取锁,当前线程尝试获取锁,如果这一时刻没有呗其他线程
获取到,则成功获取并持有锁。

lock锁:能被中断的获取锁,与synchronized不用,获取到锁的线程能够享有中断。
当获取到的锁的线程被中断时,中断异常就会被抛出,同时锁会呗释放。

lock锁:能在制定的截止时间获取锁,如果截止时间到了依旧无法获取锁则返回。


lock锁要自己去释放锁,synchronized程序执行完毕就会释放锁,或者程序抛出异常锁也会被释
放。

9、停止线程的方法

第一种:使用标识符来结束线程,标识符必须要使用可见性,使用volatile修饰。

代码:
package com.leeue.mykt;
/**
 * 
 * @classDesc: 功能描述:(停止线程第一种方法 使用volatie)
 * @author:李月
 * @Version:v1.0
 * @createTime:@Date 2018年7月8日 下午11:12:38
 *
 */
class StopThreadDemo extends Thread{
    private volatile boolean flag = true;
    @Override
    public void run() {
        System.out.println("子线程开始执行...");
        while(flag){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();

            }
        }
        System.out.println("子线程结束执行...");
    }

    public void stopThread(){
        System.out.println("调用了stopThread()方法");
        flag = false;
        System.out.println("已经讲flag修改为"+flag);
    }
}
public class StopThread {

    public static void main(String[] args) throws InterruptedException{

        StopThreadDemo threadDemo = new StopThreadDemo();
        Thread thread = new Thread(threadDemo);
        thread.start();//启动线程
        for (int i = 0; i < 10; i++) {
            Thread.sleep(1000);
            if(i==3){

                //threadDemo.interrupt();//表示让当前等待的线程抛出异常
                threadDemo.stopThread();
            }
        }

    }
}
第二种方法就是让异常抛出

9、什么是ThreadLocal?

1、什么是ThreadLocal?

答:为每一个线程提供一个局部变量。

不使用ThreadLocal来实现为每个线程提供一个局部变量的方法:
package com.leeue.mykt;
/**
 * 
 * @classDesc: 功能描述:(ThreadLock 本地线程)
 * @author:李月
 * @Version:v1.0
 * @createTime:@Date 2018年7月11日 上午10:50:00
 *
 */

class ResNumber{
    public int count = 0;
    public String getNumber(){
        count = count + 1;
        return count + "";
    }
}

class LocaThreadDemo extends Thread{
    private ResNumber resNumber;
    public LocaThreadDemo(ResNumber resNumber){
        this.resNumber = resNumber;
    }

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println(getName()+","+resNumber.getNumber());
        }
    }
}
public class ThreadLockDemo {
    public static void main(String[] args) {
        ResNumber resNumber1 = new ResNumber();
        ResNumber resNumber2 = new ResNumber();
        ResNumber resNumber3 = new ResNumber();
        LocaThreadDemo t1 = new LocaThreadDemo(resNumber1);//同时共享数据
        LocaThreadDemo t2 = new LocaThreadDemo(resNumber2);
        LocaThreadDemo t3 = new LocaThreadDemo(resNumber3);
        t1.start();
        t2.start();
        t3.start();
    }
}
使用ThreadLocal方式给每个线程创建一个属于自己的局部变量的代码
package com.leeue.mykt;

import java.util.concurrent.CountDownLatch;

/**
 * 
 * @classDesc: 功能描述:(ThreadLock 本地线程)
 * @author:李月
 * @Version:v1.0
 * @createTime:@Date 2018年7月11日 上午10:50:00
 *
 */

class ResNumber{
    public int count = 0;
    public static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){
        protected Integer  initialValue() {//注意这里
            return 0;
        }
    };//类的初始化可以这样初始化

    public String getNumber(){
         count = threadLocal.get() + 1;
         threadLocal.set(count);//还要把当前的值赋值进去
         return count + "";
    }
}

class LocaThreadDemo extends Thread{
    private ResNumber resNumber;
    public LocaThreadDemo(ResNumber resNumber){
        this.resNumber = resNumber;
    }

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println(getName()+","+resNumber.getNumber());
        }
    }
}
public class ThreadLockDemo {
    public static void main(String[] args) {
        ResNumber resNumber = new ResNumber();

        LocaThreadDemo t1 = new LocaThreadDemo(resNumber);//同时共享数据
        LocaThreadDemo t2 = new LocaThreadDemo(resNumber);
        LocaThreadDemo t3 = new LocaThreadDemo(resNumber);
        t1.start();
        t2.start();
        t3.start();
    }
}
ThreadLocalThreadLoca通过map集合
Map.put(“当前线程”,值);

猜你喜欢

转载自blog.csdn.net/leeue/article/details/80654189