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
bevolatile
之后),它们将减少循环次数,但正确的机制是使用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;
}
}