为什么可以';Java线程对象不能重新启动吗?
我知道不可能重新启动一个使用过的Java线程对象,但我找不到一个解释为什么不允许这样做;即使保证线程已经完成(参见下面的示例代码) 我不明白为什么为什么可以';Java线程对象不能重新启动吗?,java,multithreading,Java,Multithreading,我知道不可能重新启动一个使用过的Java线程对象,但我找不到一个解释为什么不允许这样做;即使保证线程已经完成(参见下面的示例代码) 我不明白为什么start()(或者至少是restart())方法不能以某种方式将线程对象的内部状态(无论它们是什么)重置为新创建线程对象时的相同值 示例代码: class ThreadExample { public static void main(String[] args){ Thread myThread = new Thread(){
start()
(或者至少是restart()
)方法不能以某种方式将线程对象的内部状态(无论它们是什么)重置为新创建线程对象时的相同值
示例代码:
class ThreadExample {
public static void main(String[] args){
Thread myThread = new Thread(){
public void run() {
for(int i=0; i<3; i++) {
try{ sleep(100); }catch(InterruptedException ie){}
System.out.print(i+", ");
}
System.out.println("done.");
}
};
myThread.start();
try{ Thread.sleep(500); }catch(InterruptedException ie){}
System.out.println("Now myThread.run() should be done.");
myThread.start(); // <-- causes java.lang.IllegalThreadStateException
} // main
} // class
类线程示例{
公共静态void main(字符串[]args){
线程myThread=新线程(){
公开募捐{
对于(int i=0;i为什么不创建一个新线程?如果您担心创建MyThread对象的开销,请将其设置为可运行,并使用新线程(MyThread)运行。start()因为他们不是那样设计的。从清晰的角度来看,这对我来说是有意义的。线程代表执行线程,而不是任务。当执行线程完成时,它完成了它的工作,如果它再次从顶部开始,它会把事情搞得一团糟
另一方面,Runnable表示一个任务,可以提交给多个线程,提交次数可以任意多。我会提出另一个问题-为什么线程对象应该是可重启的
可以说,对一个只执行给定任务一次,然后永久完成的线程进行推理(可能实现)要容易得多。要重新启动线程,需要对程序在给定时间处于何种状态有一个更复杂的视图
因此,除非你能提出一个具体的理由,说明为什么重新启动一个给定的线程
比仅仅创建一个具有相同可运行
的新线程更好,否则我认为设计决策是为了更好
(这与关于可变变量vsfinal
变量的争论大致相似——我发现最终“变量”更容易推理,更愿意创建多个新的常量变量,而不是重用现有变量。)Java线程遵循基于以下状态图的生命周期。一旦线程处于最终状态,它就结束了。这就是设计。
我知道这是不可能的
重新启动已使用的Java线程对象,但
我找不到解释为什么会这样
是不允许的;即使是
保证线程具有
已完成(请参见下面的示例代码)
我的猜测是,线程可能直接绑定到实际的本机资源(出于效率或其他限制),这些资源可能在某些操作系统中重新启动,但在其他操作系统中不可重新启动。如果Java语言的设计者允许线程重新启动,他们可能会限制JVM可以运行的操作系统的数量
想想看,我想不出一个操作系统允许线程或进程在完成或终止后重新启动。当一个进程完成时,它就死了。你想要另一个,你就重新启动它。你永远不会重新启动它
除了底层操作系统带来的效率和限制问题外,还有分析和推理问题。当事物不可变或具有离散、有限的生命周期时,您可以对并发性进行推理。就像状态机一样,它们必须有一个终端状态。它是否已启动、等待、完成?诸如此类的事情不能如果你允许线程死灰复燃的话,这是不容易推理的
你还必须考虑线程复活的含义。重新创建它的堆栈,它的状态,是安全的复活吗?你能复活一个异常结束的线程吗?等等< /P>
太多毛,太复杂。所有这些都是为了微不足道的收益。最好将线程作为不可恢复的资源保留。您可以通过使用java.util.concurrent.ThreadPoolExecutor
,或者手动让线程调用Runnable.run()
在给定的每个可运行的
上,完成后不会实际退出
这并不完全是您要问的问题,但是如果您担心线程构造时间,那么它可以帮助解决该问题。下面是一些手动方法的示例代码:
public class ReusableThread extends Thread {
private Queue<Runnable> runnables = new LinkedList<Runnable>();
private boolean running;
public void run() {
running = true;
while (running) {
Runnable r;
try {
synchronized (runnables) {
while (runnables.isEmpty()) runnables.wait();
r = runnables.poll();
}
}
catch (InterruptedException ie) {
// Ignore it
}
if (r != null) {
r.run();
}
}
}
public void stopProcessing() {
running = false;
synchronized (runnables) {
runnables.notify();
}
}
public void addTask(Runnable r) {
synchronized (runnables) {
runnables.add(r);
runnables.notify();
}
}
}
公共类可重用线程扩展线程{
private Queue runnables=new LinkedList();
私有布尔运行;
公开募捐{
运行=真;
(跑步时){
可运行r;
试一试{
已同步(可运行){
while(runnables.isEmpty())runnables.wait();
r=runnables.poll();
}
}
捕获(中断异常ie){
//别理它
}
如果(r!=null){
r、 run();
}
}
}
公共无效停止处理(){
运行=错误;
已同步(可运行){
runnables.notify();
}
}
公共void addTask(可运行的r){
已同步(可运行){
添加(r);
runnables.notify();
}
}
}
显然,这只是一个例子。它需要更好的错误处理代码,也许还需要更多的调优可用。如果您关心创建新线程对象的开销,那么您可以使用执行器
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class Testes {
public static void main(String[] args) {
Executor executor = Executors.newSingleThreadExecutor();
executor.execute(new Testes.A());
executor.execute(new Testes.A());
executor.execute(new Testes.A());
}
public static class A implements Runnable{
public void run(){
System.out.println(Thread.currentThread().getId());
}
}
}
运行此程序时,您将看到所有可运行对象都使用了相同的线程。我一直在搜索您似乎正在寻找的相同解决方案,我用这种方式解决了它。如果发生mousePressed事件,您可以终止它,也可以重用它,但它需要初始化,如下所示
class MouseHandler extends MouseAdapter{
public void mousePressed(MouseEvent e) {
if(th.isAlive()){
th.interrupt();
th = new Thread();
}
else{
th.start();
}
}
}
线程
不是线程。线程是代码的执行。线程
是程序用于创建和管理线程生命周期的对象
假设你喜欢打网球,假设你和你