繁体   English   中英

创建多线程Java类以处理数据

[英]Creating multithreading java class to process data

我想用Java实现类,该类将等待来自不同线程的新数据,当他得到它时,该类将对其进行处理,然后再次等待新数据。 我想仅使用同步,等待,notifyAll命令来实现这一点。 我尝试了一些变体:

1)使用一个线程,该线程通过命令lockObject.wait()等待。 但是,当所有活动线程完成工作时,该线程将永远等待。 当然,我可以使用stopProcess()方法,但这并不安全,因为另一个程序员可能会忘记调用它。

2)使用一个守护程序线程,它将无法工作,因为当所有活动线程完成工作后,我的守护程序线程将死亡,但他可以拥有一些必须处理的数据

3)当有新数据时-创建新线程,该线程将处理数据。 当线程处于活动状态时(他处理给定的数据),他将接收新数据。 当没有数据进入并且所有旧数据都已处理时,线程完成工作。 这个变体的缺点是-当数据经过一段时间(线程有时间处理旧数据并死亡时)时,将创建一个新线程。 我认为这对性能或/和内存不利。 我对吗?

是否可以仅使用一个或两个(可以同时使用守护程序和活动线程)线程而不使用stopProcess()方法来解决我的问题?

这里有一些代码

我对阻塞队列的认识

public class BlockingQueue<T> {
    private Queue<T> queue = new LinkedList<T>();

    public void add(T el){
        synchronized (queue){
            queue.add(el);
        }
    }

    public T getFirst(){
        synchronized (queue){
            return queue.poll();
        }
    }

    public int getSize(){
        synchronized (queue){
            return queue.size();
        }
    }
}

资料类别

public class Data {
    //some data

    public void process(){
        //process this data
    }
} 

代码的第一个变体

public class ProcessData {

    private BlockingQueue<Data> queue = new BlockingQueue<Data>();
    private boolean run = false;
    private Thread processThread;
    private Object lock = new Object();

    public synchronized void addData(Data data) throws Exception {
        if (run){
            if (data != null){
                queue.add(data);
                wakeUpToProcess();
            }
        }else{
            throw new Exception("");
        }
    }

    public synchronized void start() {
        if (!run){
            run = true;

            processThread = new Thread(new Runnable() {
                public void run() {

                    while (run || queue.getSize()!=0){

                        while(queue.getSize() == 0 && run){
                            //if stopProcess was not called
                            //and no active threads
                            //it will not die
                            waitForNewData();
                        }

                        Data cur;
                        while(queue.getSize() > 0){
                            cur = queue.getFirst();
                            cur.process();
                        }

                    }
                }
            });
            processThread.start();

        }
    }

    public synchronized void stopProcess() {
        if (run){
            run = false;
            wakeUpToProcess();
        }
    }

    private void waitForNewData(){
        try{
            synchronized (lock){
                lock.wait();
            }
        }catch (InterruptedException ex){
            ex.printStackTrace();
        }
    }

    private void wakeUpToProcess(){
        synchronized (lock){
            lock.notifyAll();
        }
    }
}

在第二个变体中,我将processThread作为守护程序。 但是,当活动线程死亡时,processThread完成工作,但是队列中有一些数据需要处理。

第三种变体

public class ProcessData {

    private BlockingQueue<Data> queue = new BlockingQueue<Data>();
    private boolean run = false;
    private Thread processThread = null;

    public synchronized void addData(Data data) throws Exception {
        if (run){
            if (data != null){
                queue.add(data);
                wakeExecutor();
            }
        }else{
            throw new Exception("ProcessData is stopped!");
        }
    }

    public synchronized void start() {
        if (!run){
            run = true;
        }
    }

    public synchronized void stopProcess() {
        if (run){
            run = false;
        }
    }

    public boolean isRunning(){
        return this.run;
    }

    protected void wakeExecutor(){
        if (processThread ==null || !processThread.isAlive()){
            processThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    Data cur;
                    while(queue.getSize() > 0){
                        cur = queue.getFirst();
                        cur.process();
                    }
                }
            });
            processThread.start();
        }
    }
}

重要的是,数据必须按顺序来自线程的顺序进行处理。

您正在认真地在这里重新发明轮子。 您想要的所有内容都可以在JDK中的java.util.concurrent包中找到

通过BlockingQueue实现生产者-消费者模式 ,您的生产者调用offer()而您的消费者线程调用take() ,直到获得可用为止。

而已。 您不需要,也不应该编写所有已编写的类。 这些并发类为您执行了所有锁定和同步操作,并且也正确地执行了此操作(不要低估)

如果不允许使用java.util.concurrent任何内容,则必须基于LinkedList类实现自己的任务队列。 我将阻塞行为封装在队列中,例如(伪代码)

synchronized Data nextTask() {
  while(the linked list is empty) {
    wait()
  }
  remove and return head of the queue
}

synchronized void addTask(Data d) {
  add d to the queue
  notifyAll()
}

然后,您可以拥有一个消费者线程,该线程连续执行类似的操作

while(true) {
  taskQueue.nextTask().process()
}

生产者线程调用taskQueue.addTask将每个任务添加到队列中。 如果最后需要正常关机,则要么需要一些“前哨值”来告知使用者线程完成操作,要么可以找到在适当时间调用Thread.interrupt()方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM