在不同 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());
}
}
我有一个主 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());
}
}