【JVM并发编程专题】——多线程协作

多线程协作——对象变量阻塞(wait/notify)

设想这样一个场景,当有线程通过条件判断发现库存不足时就不会继续执行代码;那么该线程就会进入阻塞状态,随之而来其他线程就一样进入阻塞;直到库存达到要求,所有线程唤醒,怎么样去实现这个呢???
在java中每个对象都一个wait方法,该方法就是将当前线程加入到对象的阻塞队列中

原理:阻塞信息保存在对象的等待队列中,可以利用notify()notifyAll()来打破阻塞!
操作:先加锁,后阻塞等待(利用对象阻塞线程,则必须让该线程要加锁,因为这个加入等待池的过程是非线程安全的:)
提示:注意,wait方法阻塞后则进入已经完成会释放锁,其他的线程仍然可以进入这个验证流程决定是否进入阻塞!
public void produce(int num) {
    synchronized (list) {
        //生产计划值>库存最大值
        while (list.size() + num > MAX_SIZE) {
            System.out.println("库存上限暂时无法生产");
            try {
                list.wait();【利用对象加锁】
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for (int i = 0; i < num; i++) {
            list.add(new Object());
        }
        list.notifyAll();【利用对象解锁】
    }
}

多线程协作——线程变量阻塞(join)

如何让某个线程等待另外一个线程执行完才执行呢?那就是用join方法,该方法同样会把当前线程加入到另外一个线程的等待池,当线程执行完后就唤醒

Thread  download=new Thread(){
    public void run(){
        for(int i=1;i<=100;i++){
            try {
                Thread.sleep(50);
                System.out.println("正在下载图片:"+i+"%");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
};
Thread show =new Thread(){
    public void run(){
        for(int i=1;i<=100;i++){
            try {
                download.join();//将自己的线程的阻塞打破,放到另外线程的变量中,当另外线程死亡时则它才启动
                Thread.sleep(50);
                System.out.println("正在显示图片:"+i+"%");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("图片已经显示完成");
    }
};
download.start();
show.start();
Ps:可以利用strat来控制,启动放在程序最后一行代码

多线程协作——线程次数控制(Semaphore)

如何实现线程访问量的控制,如果对达到指定数量就进入阻塞,答案是用aqs的共享模式;

 public static void main(String[] args) {
        Semaphore semaphore=new Semaphore(3);//共享锁为的限制为3
        try {
            semaphore.acquire();//尝试获取共享锁,+1;失败自旋后进入阻塞
            System.out.println("执行业务");
            semaphore.release();//取消自己的共享锁,-1
        }catch (InterruptedException e){
            e.printStackTrace();
            System.out.println("被中断了");
            return;
        }
    }

多线程协作——末尾线程控制(countDownLatch/CyclicBarrier)

当全部线程执行完后,再执行某个线程;这种数字级别的控制如何实现?

/**
 * @countDownLatch
 * 1、其他线程利用数字减少
   2、主线程一开始就会阻塞住
 */
CountDownLatch latch=new CountDownLatch(3);
ExecutorService service=Executors.newFixedThreadPool(5);
service.submit(()->{
    latch.countDown();
});
service.submit(()->{
    latch.countDown();
});
service.submit(()->{
    latch.countDown();
});
latch.await();
System.out.println("游戏加载完成");
/**
 * @CyclicBarrier
* 1、创建需指定数量;
*  2、其他线程利用await语法来减少数量后回调一个函数
 */
CyclicBarrier barrier=new CyclicBarrier(3,()->{
    System.out.println("游戏加载完成");
});
ExecutorService service=Executors.newFixedThreadPool(5);
service.submit(()->{
    barrier.await();
});
service.submit(()->{
    barrier.await();
});
service.submit(()->{
    barrier.await();
});

多线程协作——条件队列控制(Semaphore)

类似于等待通知,wait/notify;但是这是基于java内部实现的,另外一个是基于jvm实现的;

public class DataBase {
    private List<String> dataRow;
    private  ReentrantLock lock;
    private  Condition conditionWrite;
    private  Condition conditionRead;
    private volatile int writeQueueLength;
    public DataBase() {
        /**
         * @创建锁
         * 并利用锁生成条件队列,队列中就是一堆阻塞线程;利用通知——等待模式进行线程阻塞和唤醒类似于wait和notfily
         * writeQueueLength是实时得获取最新得写队列得数量,如果这个时候写锁存在,那么读锁就只能进入等待队列
         */
        this.lock = new ReentrantLock();
        this.conditionRead=lock.newCondition();
        this.conditionWrite=lock.newCondition();
        this.writeQueueLength=lock.getWaitQueueLength(conditionWrite);
        /**
         * @创建初始化数据
         */
        dataRow=new ArrayList<String>();
        dataRow.add("1");
        dataRow.add("2");
        dataRow.add("3");
        dataRow.add("4");
        dataRow.add("5");
        dataRow.add("6");
        dataRow.add("8");
    }
    /**
     * @读操作
     */
    public void select() throws  Exception{
        if(writeQueueLength>0){//写锁存在,读锁进入等待队列
            conditionRead.await();
        }
        System.out.println("开始读取数据");
    }
    /**
     * @写操作
     */
    public void update() throws Exception{
        boolean lockStatus = lock.tryLock();
        if(!lockStatus){
            conditionWrite.await();
        }
        System.out.println("正在插入数据");
        Thread.sleep(1000);
        System.out.println("插入成功");
        conditionRead.signalAll();//所有读得数据唤醒
        conditionWrite.signal();//唤醒写锁一个继续插
    }
}

JVM并发编程专题章节:
多线程管理
多线程框架
多线程测试

GodSchool
致力于简洁的知识工程,输出高质量的知识产出,我们一起努力
博主私人微信:supperlzf

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值