跟踪已访问对象的线程 - 多线程

问题描述 投票:0回答:1

我目前正在学习Java中的多线程。我正在尝试编写以下问题的代码:

老师将在白板上写下文字。一旦文本写入,教师线程将通知所有学生线程读取文本。一旦学生们都读完课文,学生线程就会通知老师。然后,老师将继续写另一篇课文,并且该过程将继续,直到老师写下“结束”。此时,所有线程都应该终止并且程序应该退出。

建议的解决方案如下:

class WhiteBoard
{
String text;
int numberOfStudents=0;
int count=0;
public void attendance()
{
numberOfStudents++;
}

    synchronized public void write(String t)
    {
        System.out.println("Teacher is Writing " +t);
        while(count!=0)
                try{wait();}catch(Exception e){}
        text=t;
        count=numberOfStudents;
        notifyAll();
    
    }
    synchronized public String read()
    {
        
        while(count==0)
                try{wait();}catch(Exception e){}
            
        String t=text;
        count--;
        if(count==0)
                notify();
        return t;
    }

}
class Teacher extends Thread
{
WhiteBoard wb;

    String notes[]={"Java is language","It is OOPs","It is Platform Independent","It supports Thread","end"};
    
    public Teacher(WhiteBoard w)
    {
        wb=w;
    }
    
    public void run()
    {
        for(int i=0;i<notes.length;i++)
            wb.write(notes[i]);
    }          

}

class Student extends Thread
{
String name;
WhiteBoard wb;
public Student(String n,WhiteBoard w)
{
name=n;
wb=w;
}

    public void run()
    {
        String text;
        wb.attendance();
                
        do
        {
            text=wb.read();
            System.out.println(name + " Reading " + text);
            System.out.flush();
        }while(!text.equals("end"));
    }

}

public class SCThread2
{
public static void main(String\[\] args)
{
WhiteBoard wb=new WhiteBoard();
Teacher t=new Teacher(wb);

        Student s1=new Student("A",wb);
        Student s2=new Student("B",wb);
        Student s3=new Student("C",wb);
        Student s4=new Student("D",wb);
        
        t.start();
        
        s1.start();
        s2.start();
        s3.start();
        s4.start();
        
    }   

}

这个解决方案的缺点是它不能阻止同一个学生线程多次阅读相同的文本,我最终得到以下输出:

Teacher is Writing Java is language
Teacher is Writing It is OOPs
Teacher is Writing It is Platform Independent
D Reading Java is language
B Reading Java is language
B Reading It is OOPs < Repeating
C Reading Java is language
C Reading It is OOPs
Teacher is Writing It supports Thread
D Reading It is OOPs
B Reading It is OOPs < Repeating
B Reading It is Platform Independent
B Reading It is Platform Independent
D Reading It is Platform Independent
C Reading It is Platform Independent
Teacher is Writing end
C Reading It supports Thread < Repeating
D Reading It supports Thread
B Reading It supports Thread
C Reading It supports Thread < Repeating
D Reading end
B Reading end
C Reading end
A Reading Java is language
A Reading end

我尝试了以下解决方案来强制同一线程不会多次读取相同的文本,但我的所有线程最终都处于等待状态。

import static java.lang.Thread.currentThread;

class WhiteBoard {
    String text;
    int numberOfStudents = 0;
    int count = 0;
    String[] names;

    public void attendance() {numberOfStudents++;}
    synchronized public void arrayInit() {
        names = new String[numberOfStudents];
    }
    synchronized public boolean hasRead(Thread t, int length) {
        String name = t.getName();
        for(int i = 0; i < length; i++) {
            if(names[i] == name) {
                return true;
            }
        }
        register(currentThread());
        return false;
    }
    synchronized public void register(Thread t) {
        String name = t.getName();
        for(int i = 0; i < names.length; i++) {
            if(names[i] == null) {
                names[i] = name;
                break;
            }
        }
    }
    synchronized public void write(String text) {
        while (count != 0) {
            try {wait();} catch (Exception e) {System.out.println(e.getMessage());}
        }
        System.out.println("Teacher is writing " + text);
        this.text = text;
        count = numberOfStudents;
        notifyAll();
    }
    synchronized public String read() {
        boolean hasRead = hasRead(currentThread(), count);
        while(count == 0 || hasRead == true) {
            try {wait();} catch (Exception e) {System.out.println(e.getMessage());}
        }
        String t = text;
        count--;
        if(count == 0) {
            arrayInit();
            notify();
        }
        return t;
    }
}

class Teacher extends Thread {
    WhiteBoard w;
    String[] notes = {"Java is language", "It is OOPs", "It is platform independent", "It supports Thread", "end"};
    public Teacher(WhiteBoard w) {
        this.w = w;
    }
    public void run() {
        for(int i = 0; i < notes.length; i++) {
            w.write(notes[i]);
        }
    }
}

class Student extends Thread {
    WhiteBoard w;
    String name;
    public Student (WhiteBoard w, String name) {
        super(name);
        this.w = w;
        this.name = name;
        w.attendance();
    }
    public void run() {
        String text;
        do {
            text = w.read();
            System.out.println(name + " Reading " + text);
            System.out.flush();
        } while (!text.equals("end"));
    }
}

public class SCThread2 {
    public static void main(String[] args) {
        WhiteBoard w = new WhiteBoard();

        Teacher t = new Teacher(w);

        Student s1 = new Student(w, "John");
        Student s2 = new Student(w,"Jonny");
        Student s3 = new Student(w, "Janardan");

        w.arrayInit();

        t.start();

        s1.start();
        s2.start();
        s3.start();
    }
}

我做错了什么?

java multithreading race-condition
1个回答
0
投票

你可以使用

import java.util.concurrent.atomic.AtomicBoolean; 

然后您可以从正在运行的线程更改变量

声明原子布尔值:

AtomicBoolean running = new AtomicBoolean(true);

在 run() 线程中使用它:

     public void run() {
        while (running.get()) {
       //your code here
       //when finished set Atomic boolean var to false:
       running.set(false)
       }
     }

在另一个函数中,您可以检查线程是否完成:

running.get()

您还可以使用 running.set(false) 从外部函数停止线程

© www.soinside.com 2019 - 2024. All rights reserved.