Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用monitor类在Java中同步线程_Java_Multithreading - Fatal编程技术网

使用monitor类在Java中同步线程

使用monitor类在Java中同步线程,java,multithreading,Java,Multithreading,下面的程序创建生成随机数的线程 如何更改监视器类,使其控制线程,使打印输出按每个线程ID的顺序打印 不接受像“调用run方法而不是start”这样的解决方案 给定的类别包括: public class Main { public static void main(String[] args) { Monitor mon = new Monitor(); for (int i = 0; i < 20; i++) new T(i,

下面的程序创建生成随机数的线程

如何更改
监视器
,使其控制线程,使打印输出按每个线程ID的顺序打印

不接受像“调用
run
方法而不是
start
”这样的解决方案

给定的类别包括:

public class Main {
    public static void main(String[] args) {
        Monitor mon = new Monitor();
        for (int i = 0; i < 20; i++)
            new T(i, mon).start();

        System.out.println("Finished");
    }
}

public类T扩展线程{
私有int-id;
私人监听;
公共T(int i,监视器m){
id=i;
mon=m;
}
私有整数计算(){
int num=0;
对于(int i=0;i<10;i++)
num=num+(int)(Math.random()*10);
返回num;
}
公开募捐{
int num=calc();
mon.print(id,num);
}
}

对于奇怪的任务,只能提出奇怪的解决方案。我的版本如下:

import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

public class Monitor {
    Map<Integer, Integer> map = new TreeMap<>();

    public synchronized void print(int id, int num) {
        map.put(id, num);
        if(map.size() == 20) {
            for(Entry<Integer, Integer> entry : map.entrySet())
            System.out.println("id=" + entry.getKey() + " num=" + entry.getValue());
        }
    }
}
import java.util.Map;
导入java.util.Map.Entry;
导入java.util.TreeMap;
公共班长{
Map Map=newtreemap();
公共同步作废打印(int-id,int-num){
map.put(id,num);
如果(map.size()==20){
for(条目:map.entrySet())
System.out.println(“id=“+entry.getKey()+”num=“+entry.getValue());
}
}
}

它解决了你的问题。“它取决于线程数”之类的异议不被接受。

对于奇怪的任务,只能提出奇怪的解决方案。我的版本如下:

import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

public class Monitor {
    Map<Integer, Integer> map = new TreeMap<>();

    public synchronized void print(int id, int num) {
        map.put(id, num);
        if(map.size() == 20) {
            for(Entry<Integer, Integer> entry : map.entrySet())
            System.out.println("id=" + entry.getKey() + " num=" + entry.getValue());
        }
    }
}
import java.util.Map;
导入java.util.Map.Entry;
导入java.util.TreeMap;
公共班长{
Map Map=newtreemap();
公共同步作废打印(int-id,int-num){
map.put(id,num);
如果(map.size()==20){
for(条目:map.entrySet())
System.out.println(“id=“+entry.getKey()+”num=“+entry.getValue());
}
}
}

它解决了你的问题。“它取决于线程数”之类的异议不被接受。

您只需要尝试打印的线程等待并阻止,直到其ID为预期ID:

public class Monitor {

    private final Object lock = new Object();
    private int expectedId = 0;

    public void print(int id, int num) {
        synchronized (lock) {
            while (id != expectedId) {
                try {
                    lock.wait();
                }
                catch (InterruptedException e) {
                    return;
                }
            }
            System.out.println("id=" + id + " num=" + num);
            expectedId++;
            lock.notifyAll();
        }
    }
}

您只需要尝试打印的线程等待并阻止,直到其ID为预期ID:

public class Monitor {

    private final Object lock = new Object();
    private int expectedId = 0;

    public void print(int id, int num) {
        synchronized (lock) {
            while (id != expectedId) {
                try {
                    lock.wait();
                }
                catch (InterruptedException e) {
                    return;
                }
            }
            System.out.println("id=" + id + " num=" + num);
            expectedId++;
            lock.notifyAll();
        }
    }
}

受@JBNizet回答的启发,我找到了这个解决方案(使用
this
作为锁):


受@JBNizet回答的启发,我找到了这个解决方案(使用
this
作为锁):


我同意,但我认为这很有趣,主要是因为只有
Monitor
可以更改。使其同步或应用任何其他类型的锁定可能更有可能按顺序打印线程ID,但这并不能保证这一点。”不接受“调用运行方法而不是启动”之类的解决方案这真的让我想把我的时间贡献给你。这个想法是,监视器将包含所有计算内容,直到现在,每次函数print调用它时,都会按id顺序打印所有准备好的计算。我同意,但我认为这很有趣,主要是因为只有
Monitor
可以更改。使其同步或应用任何其他类型的锁定可能更有可能按顺序打印线程ID,但这并不能保证这一点。”不接受“调用运行方法而不是启动”之类的解决方案这真的让我想把我的时间贡献给你。这个想法是,监视器将包含到现在为止所有的计算结果,并且每次函数print调用它时,都会按id顺序打印所有准备好的计算结果。。骗子!:-)我必须承认这也是我想到的第一个解决方案。@JBNizet,不过你的版本要好得多,voteup:-)骗子!:-)我必须承认这也是我想到的第一个解决方案。@JBNizet,你的版本要好得多,voteup:-)我找到了一个没有锁的解决方案(见我的答案)。我错过什么了吗?它有什么好处吗?您只需将此用作锁,而不是使用专用对象。这没什么变化。。。除了在我的解决方案中没有其他代码也使用我的锁来同步一个完全不同的东西之外。我也不明白THREADS_NUM常量的意义,特别是考虑到你将它设置为10,尽管你有20个线程。谢谢,你让我更清楚地理解了一些事情。我找到了一个不带锁的解决方案(见我的答案)。我错过什么了吗?它有什么好处吗?您只需将此用作锁,而不是使用专用对象。这没什么变化。。。除了在我的解决方案中没有其他代码也使用我的锁来同步一个完全不同的东西之外。我也不明白THREADS_NUM常量的意义,特别是考虑到你将它设置为10,尽管你有20个线程。谢谢,你让我更清楚地理解了一些事情。
public class Monitor {
    private int currId = 0;

    public synchronized void print(int id, int num) {
        while (id != currId) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("id=" + id + " num=" + num);
        currId++;
        notifyAll();
    }
}