gpt4 book ai didi

java - Java多线程-运行线程仅按顺序运行方法一次

转载 作者:行者123 更新时间:2023-12-03 13:16:59 25 4
gpt4 key购买 nike

在我的应用程序中,整个程序的整个生命周期内必须执行n个 Action ,一个接一个地执行。我决定不创建实现这些 Action 的方法并在while(true)循环中依次调用它们,而是决定为每个 Action 创建一个线程,并使它们执行一次run方法,然后等待所有其他线程完成操作。同样,等待轮到它,然后再次执行,依此类推...

为了实现这种机制,我创建了一个名为StatusHolder的类,该类具有一个名为threadTurn的字段(表示应执行哪个线程),一种读取该值的方法以及一个用于更新该值的方法。 (请注意,此类使用Singleton设计模式)

package Test;

public class StatusHolder
{
private static volatile StatusHolder statusHolderInstance = null;
public static volatile int threadTurn = 0;

public synchronized static int getTurn()
{
return threadTurn;
}

public synchronized static void nextTurn()
{
System.out.print("Thread turn: " + threadTurn + " --> ");

if (threadTurn == 1)
{
threadTurn = 0;
}
else
{
threadTurn++;
}

System.out.println(threadTurn);

//Wake up all Threads waiting on this obj for the right turn to come
synchronized (getStatusHolder())
{
getStatusHolder().notifyAll();
}
}

public static synchronized StatusHolder getStatusHolder()
{//Returns reference to this object

if (statusHolderInstance == null)
{
statusHolderInstance = new StatusHolder();
}

return statusHolderInstance;
}
}

然后,我有两个必须以上述方式执行的线程t1和t2。

T1类如下所示:
package Test;

public class ThreadOne implements Runnable
{
@Override
public void run()
{
while (true)
{
ThreadUtils.waitForTurn(0);

//Execute job, code's not here for simplicity
System.out.println("T1 executed");

StatusHolder.nextTurn();
}
}
}

与T2相同,只是在print语句中将waitForTurn(0)中的0更改为1,并将T1中的T1更改为T2。

我的主要内容如下:
package Test;

public class Main
{
public static void main(String[] args) throws InterruptedException
{
Thread t1 = new Thread(new ThreadOne());
Thread t2 = new Thread(new ThreadTwo());

t1.start();
t2.start();

}
}

因此,run方法如下所示:
在循环开始时,线程通过使用waitForTurn()调用检查转弯值来查看是否可以执行操作:
package Test;

public class ThreadUtils
{
public static void waitForTurn(int codeNumber)
{ //Wait until turn value is equal to the given number

synchronized (StatusHolder.getStatusHolder())
{
while (StatusHolder.getTurn() != codeNumber)
{
try
{
StatusHolder.getStatusHolder().wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}

如果两个值相等,则线程执行,否则等待nextTurn()调用唤醒StatusHolder对象,因为当转弯值更改时,所有线程均被唤醒,以便它们可以检查新的转弯值是否为他们正在等待的那个,以便他们可以运行。

请注意,nextTurn()在0到1之间循环,这是因为在这种情况下,我只有两个线程,第一个线程在turn标志为0时执行,第二个线程在turn标志为1时执行,然后再次为0,依此类推。通过更改此值,我可以轻松更改匝数。

问题:如果我运行它,一切运行正常,并且似乎可以正常运行,但是即使程序根本不会崩溃,输出控制台也会突然停止运行。我试图先放置一个t1.join(),然后再打印一个,但是该打印永远不会执行,这意味着这些线程永远不会停止/死掉,而是有时保持锁定状态。
如果我放置三个线程,这似乎更加明显:它比两个线程更早地停止。

我对线程还比较陌生,所以在这里我可能会丢失一些真正愚蠢的东西...

编辑:我不希望每次都删除一个线程并创建一个新线程:每秒创建和删除数千个obj对于垃圾收集器来说似乎是一个很大的工作量。

我之所以使用线程而不是函数的原因是,在我的实际应用程序中(此代码只是简化了)在某个特定的回合中实际上有多个线程必须并行运行,例如:将一个线程转为1,将一个线程转为1 2个一线,转3个30线,重复。因此,我想为什么不同时为单个函数创建线程并使整个过程按顺序进行。

最佳答案

这是一个不好的方法。多个线程使您可以同时执行任务。 “一个接一个地执行” Action 是单个线程的工作。

只是做这样的事情:

List<Runnable> tasks = new ArrayList<>();
tasks.add(new ThreadOne()); /* Pick better names for tasks */
tasks.add(new ThreadTwo());
...
ExecutorService worker = Executors.newSingleThreadExecutor();
worker.submit(() -> {
while (!Thread.interrupted())
tasks.forEach(Runnable::run);
});
worker.shutdown();

当您的应用程序干净退出时,请调用 worker.shutdownNow()以在这些周期结束时停止这些任务。

关于java - Java多线程-运行线程仅按顺序运行方法一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49946623/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com