Java 如何处理一个类中的多个线程?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2081747/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to deal with multiple threads in one class?
提问by hsmit
Threads are often designed in two ways (see java tutorials): either by extending the Thread class or by implementing the Runnable class. Either way, you need to specify what will run inside the thread.
线程通常以两种方式设计(参见 java 教程):通过扩展 Thread 类或通过实现 Runnable 类。无论哪种方式,您都需要指定将在线程内运行的内容。
I designed a class, an adapter towards an online resource, that retrieves different kinds of information. This class consists of methods like getInformationOfTypeA() and getInformationOfTypeB(). Both contain code to connect to online resources, so both need to be threaded to avoid deadlocks.
我设计了一个类,一个面向在线资源的适配器,用于检索不同类型的信息。此类由 getInformationOfTypeA() 和 getInformationOfTypeB() 等方法组成。两者都包含连接到在线资源的代码,因此两者都需要线程化以避免死锁。
The question is: how should I design this? I can do it like below, but then I can only implement one method:
问题是:我应该如何设计这个?我可以像下面那样做,但是我只能实现一种方法:
public class OnlineResourceAdapter implements Runnable {
public void run() {
//get stuff from resource
getInformationOfTypeA();
}
public static void main(String args[]) {
(new Thread(new OnlineResourceAdapter ())).start();
}
public void getInformationOfTypeA(){
//get information of type A
}
public void getInformationOfTypeB(){
//get information of type B
}
}
Another way would be by creating separate classes for each method, but that seems unnatural to me.
另一种方法是为每个方法创建单独的类,但这对我来说似乎不自然。
Btw: I'm developing my application in j2me
顺便说一句:我正在 j2me 中开发我的应用程序
UPDATE:
更新:
Thanks to your responses I think it is most suiting to use something like the following as methods:
感谢您的回答,我认为最适合使用以下内容作为方法:
What do you think of this:
你觉得这怎么样:
public class OnlineResourceAdapter{
public void getInformationOfTypeA(){
Thread t = new Thread(new Runnable() {
public void run() {
//do stuff here
}
});
t.start();
}
public void getInformationOfTypeB(){
Thread t = new Thread(new Runnable() {
public void run() {
//do stuff here
}
});
t.start();
}
}
What do you think of this?
你觉得这怎么样?
回答by Thorbj?rn Ravn Andersen
For each class create an anonymous class based on Runnable. This will allow you to do what you need to do inside the run() method.
为每个类创建一个基于 Runnable 的匿名类。这将允许您在 run() 方法中执行您需要执行的操作。
回答by Jon Skeet
It sounds to me like you should actually have two different classes: InformationOfTypeAFetcher
and InformationOfTypeBFetcher
, each of which should implement Runnable
. Each of them may have a reference to an instance of your OnlineResourceAdapter
(or something similar) but if they're doing different things, they should be different classes.
在我看来,您实际上应该有两个不同的类:InformationOfTypeAFetcher
和InformationOfTypeBFetcher
,每个类都应该实现Runnable
. 他们每个人都可能引用您的OnlineResourceAdapter
(或类似的)实例,但如果他们做不同的事情,他们应该是不同的类。
回答by danben
I don't see why you don't like the idea of creating multiple classes, considering Java doesn't support higher-order functions and the changeable part of your code is the algorithm.
我不明白为什么您不喜欢创建多个类的想法,因为 Java 不支持高阶函数,并且代码的可变部分是算法。
But if you wanted a single implementation of OnlineResourceAdapter
you could use the Strategy pattern and do something like this:
但是如果你想要一个单一的实现,OnlineResourceAdapter
你可以使用 Strategy 模式并执行如下操作:
public interface InformationGetter {
public void getInformation();
}
public class OnlineResourceAdapter implements Runnable {
private final InformationGetter informationGetter;
public OnlineResourceAdapter(InformationGetter i) {
this.informationGetter = i;
}
public void run() {
//get stuff from resource
i.getInformation();
}
}
and then of course you would create as many implementations of InformationGetter
as you needed.
然后当然你会InformationGetter
根据需要创建尽可能多的实现。
Come to think about it, looking back over this approach, OnlineResourceAdapter
now doesn't really add anything except making InformationGetter
runnable. So unless you have some compelling reason not to, I would say just have InformationGetter
implement Runnable
directly.
想想看,回顾这种方法,OnlineResourceAdapter
现在除了使InformationGetter
可运行之外并没有真正添加任何东西。所以除非你有一些令人信服的理由不这样做,否则我会说直接InformationGetter
实施Runnable
。
回答by Mark Byers
Many people have already suggested good methods of how to do this using several classes. Since you seem to prefer a way which doesn't require multiple classes, you might also want to consider using the constructor to give information about which resource to fetch:
许多人已经提出了如何使用几个类来做到这一点的好方法。由于您似乎更喜欢不需要多个类的方式,您可能还需要考虑使用构造函数来提供有关要获取的资源的信息:
public class OnlineResourceAdapter implements Runnable
{
private string resourceType;
public OnlineResourceAdapter(string resourceType)
{
this.resourceType = resourceType;
}
public void run() {
if (resourceType.equals("A") {
getInformationOfTypeA();
} else {
// etc..
}
}
public void getInformationOfTypeA(){
//get information of type A
}
public void getInformationOfTypeB(){
//get information of type B
}
}
Usage:
用法:
(new Thread(new OnlineResourceAdapter("A"))).start();
回答by mhaller
Use anonymous classes of type Callable
(which, in contrast to Runnable
, can return values) and execute them using an Executor
. If the logic to retrieve informationA and informationB is very similar, you may of course refactor that and use a single, parameterizes inner class of Callables.
使用匿名类型的类Callable
(与 相比Runnable
,可以返回值)并使用Executor
. 如果检索 informationA 和 informationB 的逻辑非常相似,您当然可以重构它并使用单个参数化可调用的内部类。
I'm not sure if Callable and Executor are part of J2ME spec though. In standard Java, i'd go for a Proxy
approach anyway and encapsulate the external resource as interface.
我不确定 Callable 和 Executor 是否是 J2ME 规范的一部分。在标准 Java 中,Proxy
无论如何我都会采用一种方法并将外部资源封装为接口。
public class AsyncMethodsTest {
public class OnlineResourceAdapter {
private final ExecutorService executor = Executors.newFixedThreadPool(2);
public String getInformationOfTypeA() throws InterruptedException, ExecutionException,
TimeoutException {
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
// Connect to external resource
Thread.sleep(500);
return "A";
}
};
Future<String> submit = executor.submit(callable);
return submit.get(1000, TimeUnit.MILLISECONDS);
}
public String getInformationOfTypeB() throws InterruptedException, ExecutionException,
TimeoutException {
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
// Connect to external resource
Thread.sleep(1500);
return "B";
}
};
Future<String> submit = executor.submit(callable);
return submit.get(1000, TimeUnit.MILLISECONDS);
}
}
@Test
public void testMethodCalls() throws Exception {
OnlineResourceAdapter adapter = new OnlineResourceAdapter();
assertNotNull(adapter.getInformationOfTypeA());
assertNotNull(adapter.getInformationOfTypeB());
}
}
回答by Pindatjuh
Two anonymous inner classes, like Thorbj?rn Ravn Andersen suggested vaguely above, works. Here is a code example:
两个匿名内部类,比如 Thorbj?rn Ravn Andersen 上面模糊地建议,有效。这是一个代码示例:
public class OnlineResourceAdapter {
public final Runnable typeA;
public final Runnable typeB;
public OnlineResourceAdapter() {
typeA = new Runnable() {
public void run() {
OnlineResourceAdapter.this.getInformationOfTypeA();
}
};
typeB = new Runnable() {
public void run() {
OnlineResourceAdapter.this.getInformationOfTypeB();
// one can use a non-final typed variable
// to store, which then<1>
}
};
}
public static void main(String args[]) {
OnlineResourceAdapter x = new OnlineResourceAdapter();
new Thread(x.typeA).start(); // start A
new Thread(x.typeB).start(); // start B
// <1>can be accessed here.
}
public void getInformationOfTypeA(){
// get information of type A
// return the data or directly store in OnlineResourceAdapter.
}
public void getInformationOfTypeB(){
//get information of type B
}
}
Edit: Yes, you're proposed way is a good way. You can even make the methods static. You can use "OnlineResourceAdapter.this." to access other variables to store results in.
编辑:是的,你提出的方法是一个好方法。您甚至可以将方法设为静态。您可以使用“OnlineResourceAdapter.this”。访问其他变量以存储结果。