理解Java中的多线程

理解Java中的多线程,java,multithreading,concurrency,Java,Multithreading,Concurrency,我正在学习Java中的多线程。问题陈述是:假设有一个datastruture可以包含数百万个整数,现在我想在其中搜索一个键。我想使用2个线程,这样如果其中任何一个线程找到了密钥,它应该将一个共享布尔变量设置为false,并且两个线程都应该停止进一步的处理 以下是我正在尝试的: public class Test implements Runnable{ private List<Integer> list; private Boolean value; pr

我正在学习Java中的
多线程
。问题陈述是:假设有一个datastruture可以包含数百万个整数,现在我想在其中搜索一个键。我想使用2个线程,这样如果其中任何一个线程找到了密钥,它应该将一个共享布尔变量设置为false,并且两个线程都应该停止进一步的处理

以下是我正在尝试的:

public class Test  implements Runnable{
    private List<Integer> list;
    private Boolean value;
    private int key = 27;

    public Test(List<Integer> list,boolean value) {
        this.list=list;
        this.value=value;
    }

    @Override
    public void run() {
        synchronized (value) {
            if(value){
                Thread.currentThread().interrupt();
            }
            for(int i=0;i<list.size();i++){
                if(list.get(i)==key){
                    System.out.println("Found by: "+Thread.currentThread().getName());
                    value = true;
                    Thread.currentThread().interrupt(); 
                }
                System.out.println(Thread.currentThread().getName() +": "+ list.get(i));
            }
        }

    }
}
公共类测试实现可运行{
私人名单;
私有布尔值;
私钥=27;
公共测试(列表,布尔值){
this.list=list;
这个。值=值;
}
@凌驾
公开募捐{
已同步(值){
如果(值){
Thread.currentThread().interrupt();
}

对于(int i=0;i,通过将线程的主逻辑包装在一个同步块中,该块中代码的执行变得相互排斥。线程1将进入该块,获取“value”上的锁,并在返回锁并允许线程2运行之前运行整个循环

如果只包装标志“value”的检查和设置,那么两个线程应该同时运行代码

编辑:正如其他人所讨论的,在测试类中使“value”成为一个
静态volatile boolean
,而根本不使用同步块,也会起作用。这是因为访问volatile变量就像在同步块中一样


参考:

您正在将整个代码块包装在对象
下的
同步
块下。这意味着,一旦执行到达同步块,第一个线程将保持监视器到对象
,并且任何后续线程都将阻塞,直到监视器is已发布

请注意整个块如何:

synchronized (value){
    if(value){
        Thread.currentThread().interrupt();
    }
    for(int i=0; i < list.size(); i++){
        if(list.get(i) == key){
            System.out.println("Found by: "+Thread.currentThread().getName());
            value = true;
            Thread.currentThread().interrupt(); 
        }
        System.out.println(Thread.currentThread().getName() +": "+ list.get(i));
    }
}

此外,您现在尝试执行的任务是构建Fork/Join池的目的。我建议您在Oracle的java教程中了解如何在分而治之的方法中使用Fork/Join池。

将布尔值设为静态,以便两个线程都可以访问和编辑同一个变量。这样,您就不需要传入它。然后作为一旦一个线程将其更改为true,第二个线程也将停止,因为它使用的是相同的值。

您不应该在
found
标志上获得锁-这只会确保只有一个线程可以运行。相反,请确保该标志
static
以便共享,而
volatile
则无法缓存

此外,您应该更频繁地检查标志

private List<Integer> list;
private int key = 27;
private static volatile boolean found;

public Test(List<Integer> list, boolean value) {
    this.list = list;
    this.found = value;
}

@Override
public void run() {
    for (int i = 0; i < list.size(); i++) {
        // Has the other thread found it?
        if (found) {
            Thread.currentThread().interrupt();
        }
        if (list.get(i) == key) {
            System.out.println("Found by: " + Thread.currentThread().getName());
            // I found it!
            found = true;
            Thread.currentThread().interrupt();
        }
        System.out.println(Thread.currentThread().getName() + ": " + list.get(i));
    }
}
私有列表;
私钥=27;
发现私有静态易失布尔值;
公共测试(列表,布尔值){
this.list=列表;
this.found=值;
}
@凌驾
公开募捐{
对于(int i=0;i

顺便说一句:你的两个线程都从
0
开始,并在数组中遍历-我假设你在这段代码中这样做是为了演示,你要么让它们从另一端工作,要么随机遍历。

为什么要使用
synchronized
?“共享布尔变量”建议您可能想在相关的地方使用
静态
关键字…@MuratK。因为
布尔
是共享资源?这不是正确的方法吗???@JonK在这里不
原子布尔
工作吗?也许
静态易失性布尔
可以工作。我想使用
易失性布尔
,我必须使线程并发运行。但是,我将如何共享它?访问/修改volatile变量就像它被同步块包围一样。您有两个选项:1.继续使用
同步的
块,但仅在修改或访问值的位置周围使用。2.将值设为测试的
volatile static
成员并删除同步块两个线程都在运行,直到完成执行。它们没有中断,循环正在完成如果(Thread.currentThread().isInterrupted()){System.out.println(“线程中断\n退出…”);break;}为什么我需要添加这些?为什么调用
interrupt
方法时没有停止执行?@VivekVardhan-既然
run
不能抛出中断,您必须自己检查中断。查看
interrupt()
的文档,它所做的只是设置一个标志。
private static volatile Boolean value;
private List<Integer> list;
private int key = 27;
private static volatile boolean found;

public Test(List<Integer> list, boolean value) {
    this.list = list;
    this.found = value;
}

@Override
public void run() {
    for (int i = 0; i < list.size(); i++) {
        // Has the other thread found it?
        if (found) {
            Thread.currentThread().interrupt();
        }
        if (list.get(i) == key) {
            System.out.println("Found by: " + Thread.currentThread().getName());
            // I found it!
            found = true;
            Thread.currentThread().interrupt();
        }
        System.out.println(Thread.currentThread().getName() + ": " + list.get(i));
    }
}