使用 wait/notify 的顺序线程执行
Sequential thread execution using wait/notify
现在我正在努力完成标题中的任务。我创建了 X 个线程,每个线程在循环中打印 Z 次相同的数字(从构造函数获取,例如“11111”、“222222”等)。所以结果看起来像:
111111111
222222222
333333333
111111111
222222222
333333333
对于 X = 3、Y = 9 和 Z = 2。
首先,我使用睡眠、中断并将 "next" 线程传递给前一个构造函数解决了这个问题。一个中断另一个等等。下一步是使用 wait/notify 而不是睡眠和中断来获得相同的输出。据我所知,创建共享监视器 object 是必要的,以便在每次打印后调用等待,并且在某个时刻“我应该调用 notifyAll。
当前代码是:
public class PrinterController {
private static final int THREADS_NUMBER = 5;
public static void main(String[] args) {
Printer[] printers = new Printer[THREADS_NUMBER];
for (int i = 0; i < THREADS_NUMBER; i++) {
printers[i] = new Printer(i);
printers[i].start();
}
}
}
public class Printer extends Thread {
private static int portion = 10;
private static int totalNumber = 100;
private int digit;
private static final Object monitor = new Object();
public Printer(int digit) {
this.digit = digit;
}
@Override
public void run() {
synchronized (monitor) {
int portionsNumber = totalNumber / portion;
for (int i = 0; i < portionsNumber; i++) {
printLine();
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void printLine() {
for (int j = 0; j < portion; j++) {
System.out.print(digit);
}
System.out.println();
}
}
你能帮忙改进一下吗?我找到了类似的任务,但它们不包含适当的答案。谢谢
基于 Nadir 的回答的最终解决方案:
public class Printer extends Thread {
private static int portion = 10;
private static int totalNumber = 100;
private int digit;
static Object monitor = new Object();
static Integer counter = 0;
public Printer(int digit) {
this.digit = digit;
}
@Override
public void run() {
int portionsNumber = totalNumber / portion;
for (int i = 0; i < portionsNumber; i++) {
synchronized (monitor) {
while (digit != counter) {
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
printLine();
monitor.notifyAll();
}
}
}
private void printLine() {
for (int j = 0; j < portion; j++) {
System.out.print(digit);
}
System.out.println();
counter = (counter + 1) % PrinterController.THREADS_NUMBER;
}
}
它可以通过用于同步线程(甚至确保它们是排序者)的 class 来完成。所有线程将共享同一个实例。
public class Synchronizer
{
private int nextThread;
private int maxNumThreads;
public Synchronizer(int numThreads)
{
maxNumThreads = numThreads;
nextThread = 0;
}
public void doSync(int threadId) throws Exception
{
synchronized(this)
{
while(nextThread != threadId)
{
wait();
}
}
}
public void threadDone(int threadId) throws Exception
{
synchronized(this)
{
nextThread = (threadId + 1) % maxNumThreads;
notifyAll();
}
}
}
在您的线程 run()
上,您会在打印任何内容之前调用 doSync()
。然后你会把打印的代码,然后你会调用threadDone()
,让下一个线程被释放。 id 用于执行命令。
现在我正在努力完成标题中的任务。我创建了 X 个线程,每个线程在循环中打印 Z 次相同的数字(从构造函数获取,例如“11111”、“222222”等)。所以结果看起来像:
111111111
222222222
333333333
111111111
222222222
333333333
对于 X = 3、Y = 9 和 Z = 2。 首先,我使用睡眠、中断并将 "next" 线程传递给前一个构造函数解决了这个问题。一个中断另一个等等。下一步是使用 wait/notify 而不是睡眠和中断来获得相同的输出。据我所知,创建共享监视器 object 是必要的,以便在每次打印后调用等待,并且在某个时刻“我应该调用 notifyAll。 当前代码是:
public class PrinterController {
private static final int THREADS_NUMBER = 5;
public static void main(String[] args) {
Printer[] printers = new Printer[THREADS_NUMBER];
for (int i = 0; i < THREADS_NUMBER; i++) {
printers[i] = new Printer(i);
printers[i].start();
}
}
}
public class Printer extends Thread {
private static int portion = 10;
private static int totalNumber = 100;
private int digit;
private static final Object monitor = new Object();
public Printer(int digit) {
this.digit = digit;
}
@Override
public void run() {
synchronized (monitor) {
int portionsNumber = totalNumber / portion;
for (int i = 0; i < portionsNumber; i++) {
printLine();
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void printLine() {
for (int j = 0; j < portion; j++) {
System.out.print(digit);
}
System.out.println();
}
}
你能帮忙改进一下吗?我找到了类似的任务,但它们不包含适当的答案。谢谢
基于 Nadir 的回答的最终解决方案:
public class Printer extends Thread {
private static int portion = 10;
private static int totalNumber = 100;
private int digit;
static Object monitor = new Object();
static Integer counter = 0;
public Printer(int digit) {
this.digit = digit;
}
@Override
public void run() {
int portionsNumber = totalNumber / portion;
for (int i = 0; i < portionsNumber; i++) {
synchronized (monitor) {
while (digit != counter) {
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
printLine();
monitor.notifyAll();
}
}
}
private void printLine() {
for (int j = 0; j < portion; j++) {
System.out.print(digit);
}
System.out.println();
counter = (counter + 1) % PrinterController.THREADS_NUMBER;
}
}
它可以通过用于同步线程(甚至确保它们是排序者)的 class 来完成。所有线程将共享同一个实例。
public class Synchronizer
{
private int nextThread;
private int maxNumThreads;
public Synchronizer(int numThreads)
{
maxNumThreads = numThreads;
nextThread = 0;
}
public void doSync(int threadId) throws Exception
{
synchronized(this)
{
while(nextThread != threadId)
{
wait();
}
}
}
public void threadDone(int threadId) throws Exception
{
synchronized(this)
{
nextThread = (threadId + 1) % maxNumThreads;
notifyAll();
}
}
}
在您的线程 run()
上,您会在打印任何内容之前调用 doSync()
。然后你会把打印的代码,然后你会调用threadDone()
,让下一个线程被释放。 id 用于执行命令。