Java多线程不';似乎没有正常工作

Java多线程不';似乎没有正常工作,java,multithreading,Java,Multithreading,我有一个处理某些事情的类。我正在尝试并行运行这个类的多个实例 但是,我不确定在TaskManager.startAll()中,当我调用r.go()时,这是否会导致r开始在自己的线程中运行,还是在主线程中运行 我得到的总执行时间似乎非常高,尽管我尝试优化,但似乎没有任何效果。此外,如果我在Netbeans中的项目上运行探查器,它会将所有线程显示为休眠线程。所以我想知道我是否做错了什么 这是该类的结构: public class TaskRunner implements Runnable {

我有一个处理某些事情的类。我正在尝试并行运行这个类的多个实例

但是,我不确定在
TaskManager.startAll()
中,当我调用
r.go()
时,这是否会导致r开始在自己的线程中运行,还是在主线程中运行

我得到的总执行时间似乎非常高,尽管我尝试优化,但似乎没有任何效果。此外,如果我在Netbeans中的项目上运行探查器,它会将所有线程显示为休眠线程。所以我想知道我是否做错了什么

这是该类的结构:

public class TaskRunner implements Runnable {
   private boolean isRunning = false;
   public void run() {
        while(true) {
            while (! running) {
                try {
                    Thread.sleep(1);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            process();
        }
    }

    public void go() {
       isRunning = true;
    }

    public void stop() {
       isRunning = false;
    }

    private void process() {
       //Do some number crunching and processing here
    }
}
以下是如何运行/管理这些功能:

public class TaskManager {
     private ArrayList<TaskRunner> runners = new ArrayList<>();
     public TaskManager() {
        for (int i = 0; i < 10; i++) {
            TaskRunner r = new TaskRunner();
            new Thread(r).start();
            runners.add(r);
        }
     }

     public void startAll() {
        for (TaskRunner r : runners) {
           r.go();
         }
     }
}
公共类任务管理器{
private ArrayList runners=new ArrayList();
公共任务管理器(){
对于(int i=0;i<10;i++){
TaskRunner r=新的TaskRunner();
新线程(r.start();
添加(r);
}
}
公共图书馆{
for(TaskRunner r:Runner){
r、 go();
}
}
}
但是,我不确定在TaskManager.startAll()中,当我调用r.go()时,这是否会导致r开始在自己的线程中运行,还是在主线程中运行

因此,我的第一个评论是,您应该将
isRunning
设置为
volatile
,因为它是在线程之间共享的。如果线程在变为真时没有启动(或者启动时似乎延迟),那么我怀疑这是您的问题
volatile
在线程之间提供内存同步,因此等待更改的线程将立即看到调用
go()
并对
isRunning进行更改的线程

我不会像这样旋转,而是使用wait/notify:

// this synchronizes on the instance of `TaskRunner`
synchronized (this) {
   // always do your wait in a while loop to protect against spurious wakeups
   while (!isRunning && !Thread.currentThread().isInterrupted()) {
      try {
          // wait until the notify is called on this object
          this.wait();
      } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
          e.printStackTrace();
      }
 }
然后在
go()
方法中,您应该执行以下操作<代码>停止()
类似

public void go() {
    synchronized (this) {
       isRunning = true;
       this.notifyAll();
    }
}
请注意,您应该小心处理线程中断。在whilerunning循环中测试
isInterrupted()
,并在抛出
InterruptedException
时重新中断线程始终是一种好模式

我得到的总执行时间似乎非常高,尽管我尝试优化,但似乎没有任何效果。此外,如果我在Netbeans中的项目上运行探查器,它会将所有线程显示为休眠线程

因此,尽管线程大部分处于休眠状态,但它们仍然每秒循环1000次,这是因为您的
Thread.sleep(1)
。如果您增加睡眠时间(在使
isRunning
be
volatile
之后),它们将减少循环次数,但正确的机制是使用wait/notify向线程发送信号。

事实上,您没有“做得对”。如果您想创建多线程Java应用程序,从
java.util.concurrent
包开始

从代码中可以看出,您希望并行运行十个任务。我假设在“数字运算和处理”之后,您将希望聚合结果并在主线程中对其进行处理。为此,
ExecutorService
invokeAll()
方法运行良好

首先,实现
Callable
来完成
process()
方法中显示的工作

final class YourTask implements Callable<YourResults> {

  private final YourInput input;

  YourTask(YourInput input) {
    this.input = input;
  }

  @Override
  public YourResults call() 
    throws Exception 
  {
    /* Do some number crunching and processing here. */
    return new YourResults(...);
  }

}

糟糕的解决方案,糟糕透顶。首先,我强烈建议你开始阅读一些教程,比如 第二,如果线程应该等待一个信号去做某项工作,那么为什么不等待它们呢!!!!!,像这样的

import java.util.ArrayList;
public class TaskManager
{
     //////////////////////
     public volatile static Signal wait=new Signal();
     ////////////////////// 
     private ArrayList<TaskRunner> runners = new ArrayList<>();
     public TaskManager()
     {
        for (int i = 0; i < 10; i++)
        {
            TaskRunner r = new TaskRunner();
            new Thread(r).start();
            runners.add(r);
        }
        try {
          Thread.sleep(1000);
        startAll();
          Thread.sleep(1000);
        pauseAll();
          Thread.sleep(1000);
        startAll();
        Thread.sleep(1000);
        haltAll();System.out.println("DONE!");
        }catch(Exception ex){}
     }

     public void startAll()
     {
         synchronized(wait){
                wait.setRun(true);;
                wait.notifyAll();
         }
     }
     public void pauseAll(){
     wait.setRun(false);
     }
     public void haltAll(){
      for(TaskRunner tx:runners){tx.halt();}
      }
     public static void main(String[] args) {
      new TaskManager();
    }
}

class TaskRunner implements Runnable
{
   private Thread thisThread;
   private volatile boolean run=true;
   public void run()
    {
        thisThread=Thread.currentThread();
        while(run){
        if(!TaskManager.wait.isRun()){
        synchronized(TaskManager.wait)
        {
             if(!TaskManager.wait.isRun()){
               System.out.println("Wait!...");
                try
                {
                  TaskManager.wait.wait();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                    break;
                }
             }
        }}
         process();
     }
    }
    private double r=Math.random();
    private void process(){System.out.println(r);try {
      Thread.sleep(10);
    } catch (Exception e) {
      // TODO: handle exception
    }}
    public void halt(){run=false;thisThread.interrupt();}
}
class Signal{
  private boolean run=false;

  public boolean isRun() {
    return run;
  }

  public void setRun(boolean run) {
    this.run = run;
  }

}
import java.util.ArrayList;
公共类任务管理器
{
//////////////////////
公共易失性静态信号等待=新信号();
////////////////////// 
private ArrayList runners=new ArrayList();
公共任务管理器()
{
对于(int i=0;i<10;i++)
{
TaskRunner r=新的TaskRunner();
新线程(r.start();
添加(r);
}
试一试{
睡眠(1000);
斯塔尔();
睡眠(1000);
pauseAll();
睡眠(1000);
斯塔尔();
睡眠(1000);
haltAll();System.out.println(“完成!”);
}捕获(例外情况除外){}
}
公共图书馆
{
已同步(等待){
等等,setRun(真);;
等等,notifyAll();
}
}
公共无效pauseAll(){
wait.setRun(false);
}
公众假期{
对于(TaskRunner tx:runners){tx.halt();}
}
公共静态void main(字符串[]args){
新任务管理器();
}
}
类TaskRunner实现Runnable
{
私有线程thisThread;
private volatile boolean run=true;
公开募捐
{
ThistThread=Thread.currentThread();
while(运行){
如果(!TaskManager.wait.isRun()){
已同步(TaskManager.wait)
{
如果(!TaskManager.wait.isRun()){
System.out.println(“Wait!”);
尝试
{
TaskManager.wait.wait();
}
捕获(例外e)
{
e、 printStackTrace();
打破
}
}
}}
过程();
}
}
private double r=Math.random();
private void process(){System.out.println(r);请重试{
睡眠(10);
}捕获(例外e){
//TODO:处理异常
}}
public void halt(){run=false;thisThread.interrupt();}
}
类信号{
私有布尔运行=false;
公共布尔值isRun(){
回程;
}
公共void setRun(布尔运行){
this.run=run;
}
}
在上面的示例中,所有运行程序都会一直工作,直到信号run boolean为true,并且每次需要暂停线程时,simple TaskManager类都会将tit设置为false。关于暂停,它只是将shutdown(run)标志设置为false,还设置了interr
import java.util.ArrayList;
public class TaskManager
{
     //////////////////////
     public volatile static Signal wait=new Signal();
     ////////////////////// 
     private ArrayList<TaskRunner> runners = new ArrayList<>();
     public TaskManager()
     {
        for (int i = 0; i < 10; i++)
        {
            TaskRunner r = new TaskRunner();
            new Thread(r).start();
            runners.add(r);
        }
        try {
          Thread.sleep(1000);
        startAll();
          Thread.sleep(1000);
        pauseAll();
          Thread.sleep(1000);
        startAll();
        Thread.sleep(1000);
        haltAll();System.out.println("DONE!");
        }catch(Exception ex){}
     }

     public void startAll()
     {
         synchronized(wait){
                wait.setRun(true);;
                wait.notifyAll();
         }
     }
     public void pauseAll(){
     wait.setRun(false);
     }
     public void haltAll(){
      for(TaskRunner tx:runners){tx.halt();}
      }
     public static void main(String[] args) {
      new TaskManager();
    }
}

class TaskRunner implements Runnable
{
   private Thread thisThread;
   private volatile boolean run=true;
   public void run()
    {
        thisThread=Thread.currentThread();
        while(run){
        if(!TaskManager.wait.isRun()){
        synchronized(TaskManager.wait)
        {
             if(!TaskManager.wait.isRun()){
               System.out.println("Wait!...");
                try
                {
                  TaskManager.wait.wait();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                    break;
                }
             }
        }}
         process();
     }
    }
    private double r=Math.random();
    private void process(){System.out.println(r);try {
      Thread.sleep(10);
    } catch (Exception e) {
      // TODO: handle exception
    }}
    public void halt(){run=false;thisThread.interrupt();}
}
class Signal{
  private boolean run=false;

  public boolean isRun() {
    return run;
  }

  public void setRun(boolean run) {
    this.run = run;
  }

}