我正在尝试使用信号量同步一些线程。目标是按顺序重复打印1(8),2(4),4(2)和8(1)的序列。我的程序正常工作,直到大约90%完成,然后它在2和4上混乱。我无法弄清楚可能导致这个问题的生活。有什么建议?
public class ThreadSync
{
private static int count = 100;
private static Semaphore printSomeOnes = new Semaphore(1);
private static Semaphore printSomeTwos = new Semaphore(0);
private static Semaphore printSomeFours = new Semaphore(0);
private static Semaphore printSomeEights = new Semaphore(0);
private static boolean runFlag = true;
public static void main( String[] args ) {
// create and start each runnable
Runnable task1 = new TaskPrint1();
Runnable task2 = new TaskPrint2();
Runnable task3 = new TaskPrint4();
Runnable task4 = new TaskPrint8();
Thread thread1 = new Thread( task1 );
Thread thread2 = new Thread( task2 );
Thread thread3 = new Thread( task3 );
Thread thread4 = new Thread( task4 );
thread1.start();
thread2.start();
thread3.start();
thread4.start();
// Let them run for 500ms
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
// put up the stop sign
runFlag=false;
thread4.interrupt();
thread3.interrupt();
thread2.interrupt();
thread1.interrupt();
}
public static class TaskPrint1 implements Runnable
{
public void run(){
while (runFlag) {
for(int i = 0; i < count; i++){
if(i % 8 == 0){
try {
printSomeOnes.acquire();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.printf( "%s\n", "1");
if(i % 8 == 0){
printSomeTwos.release();
}
}
}
}
}
public static class TaskPrint2 implements Runnable
{
public void run(){
while (runFlag) {
for(int i = 0; i < count; i++){
if(i % 4 == 0){
try {
printSomeTwos.acquire();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.printf( "%s\n", "2");
if(i % 4 == 0){
printSomeFours.release();
}
}
}
}
}
public static class TaskPrint4 implements Runnable
{
public void run(){
while (runFlag) {
for(int i = 0; i < count; i++){
if(i % 2 == 0){
try {
printSomeFours.acquire();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.printf( "%s\n", "4");
if(i % 2 == 0){
printSomeEights.release();
}
}
}
}
}
public static class TaskPrint8 implements Runnable
{
public void run(){
while (runFlag) {
for(int i = 0; i < count; i++){
try {
printSomeEights.acquire();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.printf( "%s\n", "8");
printSomeOnes.release();
}
}
}
}
}
答案 0 :(得分:0)
我所做的一些改变:
删除runFlag
使用Thread.currentThread().isInterrupted()
,这是解决此问题的最佳方法。当发生InterruptedException
时,只需重置线程的中断标志,以便更高级别的代码对其起作用。
为:
try {
printSomeOnes.acquire();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
break;
}
此时只有InterruptedException
发生时,只需重置标志即可
while (!Thread.currentThread().isInterrupted()) {
可以采取相应行动。我们应该采用哪种方式解决这个问题。希望它有所帮助。
public class ThreadSync {
private static int count = 100;
private static Semaphore printSomeOnes = new Semaphore(1);
private static Semaphore printSomeTwos = new Semaphore(0);
private static Semaphore printSomeFours = new Semaphore(0);
private static Semaphore printSomeEights = new Semaphore(0);
private static volatile boolean runFlag = true;
public static void main(String[] args) {
// create and start each runnable
Runnable task1 = new TaskPrint1();
Runnable task2 = new TaskPrint2();
Runnable task3 = new TaskPrint4();
Runnable task4 = new TaskPrint8();
Thread thread1 = new Thread(task1);
Thread thread2 = new Thread(task2);
Thread thread3 = new Thread(task3);
Thread thread4 = new Thread(task4);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
// Let them run for 500ms
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
// put up the stop sign
// runFlag=false;
thread4.interrupt();
thread3.interrupt();
thread2.interrupt();
thread1.interrupt();
}
public static class TaskPrint1 implements Runnable {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
for (int i = 0; i < count; i++) {
if (i % 8 == 0) {
try {
printSomeOnes.acquire();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
break;
}
}
System.out.printf("%s\n", "1");
if (i % 8 == 0) {
printSomeTwos.release();
}
}
}
}
}
public static class TaskPrint2 implements Runnable {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
for (int i = 0; i < count; i++) {
if (i % 4 == 0) {
try {
printSomeTwos.acquire();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
break;
}
}
System.out.printf("%s\n", "2");
if (i % 4 == 0) {
printSomeFours.release();
}
}
}
}
}
public static class TaskPrint4 implements Runnable {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
for (int i = 0; i < count; i++) {
if (i % 2 == 0) {
try {
printSomeFours.acquire();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
break;
}
}
System.out.printf("%s\n", "4");
if (i % 2 == 0) {
printSomeEights.release();
}
}
}
}
}
public static class TaskPrint8 implements Runnable {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
for (int i = 0; i < count; i++) {
try {
printSomeEights.acquire();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
break;
}
System.out.printf("%s\n", "8");
printSomeOnes.release();
}
}
}
}
}