我是使用多线程的新手,但我想异步调用一个方法(在一个单独的Thread
中),而不是同步调用它。基本的想法是我在内存中创建一个带有对象的套接字服务器,因此对于每个客户端,我将不得不异步运行object.getStuff()
之类的内容。
我发现的两个结构是:
this
和runnable
类。 此外this
方法需要返回值 - 是否需要使用Executor
和Callable
来实现此目的?有人能指出我正确的方向来实现这个吗?
我已经尝试了实现选项2,但这似乎并不是同时处理:
public class Test {
private ExecutorService exec = Executors.newFixedThreadPool(10);
public Thing getStuff(){
class Getter implements Callable<Thing>{
public Thing call(){
//do collection stuff
return Thing;
}
}
Callable<Thing> callable = new Getter();
Future<Thing> future = exec.submit(callable);
return future.get();
}
}
我正在为服务器实例化一个测试对象,并为每个客户端连接调用getStuff()。
答案 0 :(得分:2)
关于并发的Java教程有一个很好的部分。它在https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html。从本质上讲,您可以实施Runnable
或Callable
,也可以继承Thread
。
您可以编写一个扩展Thread
的类,包括一个匿名内部类。实例化它,然后调用start()
方法。
public class MyThread extends Thread {
public void run() {
System.out.println("This is a thread");
}
public static void main(String[] args) {
MyThread m = new MyThread();
m.start();
}
}
您可以编写一个实现Runnable
的类,然后将实例包装在Thread
中并调用start()
。非常像以前的。
public class MyRunnable implements Runnable {
public void run() {
System.out.println("This is a thread");
}
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
(new Thread(r)).start();
}
}
Runnable
不允许返回值。如果您需要,则需要实现Callable
。 Callable
看起来很像Runnable
,除非您覆盖call()
方法而不是run()
方法,并且您需要将其提供给ExecutorService
。< / p>
public class MyCallable implements Callable<Integer> {
public Integer call() {
System.out.println("A thread using Callable<Integer>");
return 42;
}
public static void main(String[] args) {
MyCallable c = new MyCallable();
Future<Integer> f = Executors.newSingleThreadExecutor().submit(c));
System.out.println("The thread returned: " +
f.get());
}
}
答案 1 :(得分:1)
我发现的两个结构是1)让类实现Runnable并线程化'this'和2)在方法中声明一个runnable类。
选项(2)可能更好。如果他们有更多类,那么大多数程序都会得到改进,而不是更少。程序中的每个命名实体 - 每个包,类,方法,等等 - 应该只有一个责任。在您的选项(1)中,您要求班级做两个事情。
对于您的选项(2),您实际上不必声明整个班级。您可以使用匿名内部类,或者如果您可以一直使用Java8,则可以使用 lambda表达式。谷歌让任何一方了解更多。
此外,此方法需要返回值。
经典的方法是让Runnable
对象在线程终止之前通过其自己的一个字段返回值。然后父线程可以检查对象并在之后获得返回值。
是否有必要使用Executor和Callable来实现这一目标?
必要吗?很多人认为ExecutorService
是 Good Thing。
听起来您正在创建一个为多个客户端提供服务的服务器。这些客户端是否不断连接和断开连接?使用线程池(即ThreadPoolExecutor
)的优点是它可以使您的程序不再持续创建和销毁线程(例如,每次客户端连接/断开连接时)。创建和销毁线程非常昂贵。如果你有很多客户端连接和断开连接,那么使用线程池可能会对服务器的性能产生很大的影响。
答案 2 :(得分:0)
自己创建和管理线程通常是不好的方法。
正如您已经指出的那样 - 使用Executors
实用程序类来创建执行程序并向其提交Callable
。
答案 3 :(得分:0)
public class RunWResult implements Runable{
private volatile ResultType var;
//the thread method
public void run(){
...
//generate a result and save it to var
var = someResult();
//notify waiting threads that a result has been generated
synchronized(this){
notify();
}
}
public ResultType runWithResult(){
//run the thread generating a result
Thread t = new Thread(this);
t.start();
//wait for t to create a result
try{
wait();
}catch(InterruptedException e){}
//return the result
return var;
}
}