在不同 class 上使用线程生成的值的最佳方式

Best way to use value generated by thread on different class

我有一个主 class 和另外两个 class 和一个线程。当线程完成执行时,该结果应该可用于所有三个 classes。所以基本上就像一个触发函数。什么解决方案可以解决这个问题?

您应该使用单例类并将其用作容器:

public class ClassicSingleton {
  private static ClassicSingleton instance = null;
  private String text;
 // Add your values 
  protected ClassicSingleton() {

}
public void setText(String text){
 this.text=text;
}
public static ClassicSingleton getInstance() {
  if(instance == null) {
     instance = new ClassicSingleton();
  }
  return instance;
  }
}

然后您可以在线程中调用它,例如:

ClassSingleton singleton = getInstance();
singleton.setText("something");

您必须保留需要在线程内通知的对象列表。通知他们,即在线程完成执行后调用一个方法或在所有这些 类 中设置一个布尔值。

http://www.tutorialspoint.com/design_pattern/observer_pattern.htm

一个有效的简单示例如下所示:

import java.util.ArrayList;
import java.util.Collection;

public class MainClass implements ResultReceiver {

    public static void main(String[] args) {

        SeparateThread separateThread = new SeparateThread();
        separateThread.registerForResult(new MainClass());
        separateThread.registerForResult(new OtherClass1());
        separateThread.registerForResult(new OtherClass2());
        separateThread.start();
    }

    @Override
    public void receive(String result) {
        System.out.println("MainClass.receive(\"" + result + "\")");
    }

}

class SeparateThread extends Thread {

    private static final Collection<ResultReceiver> receivers = new ArrayList<>();

    public void registerForResult(ResultReceiver receiver) {
        receivers.add(receiver);
    }

    @Override
    public void run() {

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String result = "Hello" + " " + "world";

        for (ResultReceiver receiver : receivers) {
            receiver.receive(result);
        }
    }

}

class OtherClass2 implements ResultReceiver {

    @Override
    public void receive(String result) {
        System.out.println("OtherClass2.receive(\"" + result + "\")");
    }

}

class OtherClass1 implements ResultReceiver {

    @Override
    public void receive(String result) {
        System.out.println("OtherClass1.receive(\"" + result + "\")");
    }

}

interface ResultReceiver {
    void receive(String result);
}

然而,在主线程中等待结果并处理所有结果(更复杂的解决方案)在大多数情况下更可靠。

我认为一个简单的解决方案是使用 Thread.wait() 和 Thread.notifyAll():

Worker class(也是 Main class)启动处理程序和 worker。工人等待 1 秒,然后 'publishes' 通过 notifyAll();

结果
public class Worker extends Thread {

    private String result;

    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (final InterruptedException e) {
            e.printStackTrace();
        }
        result = "Result " + System.currentTimeMillis();

        System.out.println("Worker has result:" + result);

        synchronized (this) {
            notifyAll();
        }
    }

    public String getResult() {
        return result;
    }

    public static void main(final String[] args) {
        final Worker worker = new Worker();

        new Handler("Handler 1", worker).start();
        new Handler("Handler 2", worker).start();
        new Handler("Handler 3", worker).start();

        worker.start();
    }
}

处理程序class 等待结果并打印出来:

public class Handler extends Thread {

    private final String name;
    private final Worker worker;

    public Handler(final String name, final Worker worker) {
        this.name = name;
        this.worker = worker;
    }

    @Override
    public void run() {

        synchronized (worker) {
            try {
                System.out.println(name + " waiting for worker...");
                worker.wait();
            } catch (final InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name + " result: " + worker.getResult());
        }
    }
}

示例输出:

Handler 1 waiting for worker...
Handler 3 waiting for worker...
Handler 2 waiting for worker...
Worker has result:Result 1422364603864
Handler 2 result: Result 1422364603864
Handler 3 result: Result 1422364603864
Handler 1 result: Result 1422364603864

强制 3 类 或任意数量的 类 以等待结果的最佳方法是使用 CyclicBarrier。但这不是你在最后一行所说的那种触发效果。

public class ResultThread implements Runnable{
    private CountDownLatch latch = new CountDownLatch(1);
    private String result;

    public String getResult() throws InterruptedException {
        System.out.println("GetResult...");
        latch.await();
        System.out.println("Got Result ...");
        return result;
    }
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {e.printStackTrace();        }
        result = " Thread done at " + System.currentTimeMillis();
        System.out.println("result calculated");
        latch.countDown();
    }

    public static void main(String[] args) throws InterruptedException {
        ResultThread rThread = new ResultThread();
        new Thread(rThread).start();
        System.out.println(rThread.getResult());
    }
}

对于此类触发器,将 Latch 替换为 Lock.wait 和 notifyAll

public class ResultThread implements Runnable{
    private Lock resultLock = new ReentrantLock();
    private volatile boolean resultDone = false;
    private String result;

    public String getResult() throws InterruptedException {
        System.out.println("GetResult...");
        if(!resultDone){
            synchronized (resultLock){
                System.out.println("Waiting...");
                resultLock.wait();
            }
        }
        System.out.println("Got Result ...");
        return result;
    }
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {e.printStackTrace();        }
        result = " Thread done at " + System.currentTimeMillis();
        System.out.println("result calculated");
        resultDone = true;
        synchronized (resultLock){
            resultLock.notifyAll();
        }

    }

    public static void main(String[] args) throws InterruptedException {
        ResultThread rThread = new ResultThread();
        new Thread(rThread).start();
        System.out.println(rThread.getResult());
    }
}