外界参数控制多线程队列进行与否

业务场景,最近遇到个需求,就是通过点击开始/继续要控制任务进度,
刚开始想到了线程wait,notify
本人是个比较懒得人,一想到要写那么多代码空值,要等待,唤醒,睡眠啥的就觉得麻烦,出现调度执行问题好不好排查。
于是想到了Queue,它里面有java  的lock能帮助我,于是有了如下的代码
package org.example.file.mult;
//函数式接口
@FunctionalInterface
public interface FuncationCallback {
    void callback(String param);
}

 

package org.example.file.mult;

import java.util.ArrayList;

public class FuncationCallbackImpl {
   //函数式 回调参数处理
    public FuncationCallbackImpl(ArrayList arrayList,final FuncationCallback funcationCallback) {
        arrayList.forEach(ele->{
            funcationCallback.callback(ele+"456789");
        });

    }
}

 

package org.example.file.mult;


import org.apache.tomcat.util.threads.TaskThreadFactory;

import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Securite {
    //有界队列,根据实际业务设置即可
    public static ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
   //静态线程池,一会多线程执行能用到,根据自己的机器性能配置即可
    public static Executor executor = new ThreadPoolExecutor(3, 10, 2000, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10),
new TaskThreadFactory("测试队列", false, 7)); public Securite() { } public void exec(Integer ele) { queue.offer(ele); } //全局静态 内存可见性常量,空值任务暂停使用 public static volatile int a = 0;//刷回主内存 //静态内部类,有利于在主程序空值进度 public static class MultTask implements Runnable { private ArrayBlockingQueue<Integer> arrayBlockingQueue1; //线程-队列构造器 便于每个线程都能冲全局队列取值 public MultTask(ArrayBlockingQueue<Integer> arrayBlockingQueue1) { this.arrayBlockingQueue1 = arrayBlockingQueue1; } @Override public void run() { //循环,这里要注意和arrayBlockingQueue1.take()配合使用,避免空悬打满cpu while (true) { try { //当参数等于8时,后面的线程停止取队列的元素进行操作,来达到外界可控的目的 if (a == 8) { System.out.println("开始终端了"); Thread.sleep(5000); System.out.println("5秒后继续"); // a = 51; return; } Integer take = arrayBlockingQueue1.take(); String name = Thread.currentThread().getName(); ArrayList arrayList = new ArrayList(); arrayList.add(take); //队列每次取值后再回调函数里处理后的值 new FuncationCallbackImpl(arrayList, new FuncationCallback() { @Override public void callback(String param) { System.out.println("返回param:" + param); } }); //TODO 根据自己的业务进行后续处理 System.out.println(">>>>>>>>>>>>>>>>>>>>>:" + take + "<><><><><><><>:" + name); } catch (InterruptedException e) { } } } } // public static void main(String[] args) throws InterruptedException { // Securite securite = new Securite(); // for (int i = 0; i < 10; i++) { // if (i == 8) { // a = 8; // } // securite.exec(i); // executor.execute(new MultTask(queue)); // // } // System.out.println("10s后在运行一次"); // Thread.sleep(1500); // securite.exec(10); // executor.execute(new MultTask(queue)); // // } }

 

知识普及:
volatile可见性
JMM规定所有的变量都在主内存,主内存是公共的所有线程都可以访问,线程对变量的操作必须是在自己的工作内存中。
现在假设主物理内存中存在一个变量他的值为7,现在线程A和线程B要操作这个变量所以他们首先要将这个变量的值拷贝一份放到自己的工作内存中,如果A将这个值改为1,这时候线程B要使用这个变量但是B线程工作内存中的变量副本是7不是新修改的1这就会出现问题。所以JMM规定线程解锁前一定要将自己工作内存的变量写回主物理内存中,线程加锁前一定要读取主物理内存的值。也就是说一旦A修改了变量值,B马上能知道并且能更新自己工作内存的值。这就是可见性。

 

posted @ 2023-03-19 17:23  余生请多指教ANT  阅读(8)  评论(0编辑  收藏  举报