Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.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
如何在Java中发出线程安全的暂停信号_Java_Multithreading_Synchronization - Fatal编程技术网

如何在Java中发出线程安全的暂停信号

如何在Java中发出线程安全的暂停信号,java,multithreading,synchronization,Java,Multithreading,Synchronization,我有一堆线程同时运行。有时,一个线程需要通知其他线程等待它完成一个作业,并再次发出信号让它们继续。由于我对Java的同步有些陌生,我想知道做这种事情的正确方法是什么。我的代码是这样的: private void Concurrent() { if (shouldRun()) { // notify threads to pause and wait for them DoJob(); // resume threads }

我有一堆线程同时运行。有时,一个线程需要通知其他线程等待它完成一个作业,并再次发出信号让它们继续。由于我对Java的同步有些陌生,我想知道做这种事情的正确方法是什么。我的代码是这样的:

private void Concurrent() {
    if (shouldRun()) {
        // notify threads to pause and wait for them
        DoJob();
        // resume threads
    }

    // Normal job...
}
public class TestCrawler extends WebCrawler {

private Pause mPause;

public TestCrawler(Pause pPause) {
    this.mPause = pPause;
}

private SingleThread()
{
        //When this function is running, no other crawler should do anything
}

@Override
public void visit(Page page) {
    if(SomeCriteria())
    {
        //only enter the crucial part once if it has to be exclusive
        this.mPause.probe();
        //make all other crawlers stop until I finish
        this.mPause.pause(true);
        SingleThread();
        //let them resume
        this.mPause.pause(false);
    }
    this.mPause.probe();
    //Normal Stuff
}
}
更新: 请注意,我编写的代码位于一个类中,每个线程都将执行该类。我无法访问这些线程,也无法访问它们的运行方式。我只是内线

更新2: 我的代码来自爬虫类。爬虫类(crawler4j)知道如何处理并发性。我只需要在运行函数之前暂停其他爬虫程序,然后再恢复它们。此代码是我的爬虫程序的基础:

   public class TestCrawler extends WebCrawler {
    private SingleThread()
    {
        //When this function is running, no other crawler should do anything
    }

    @Override
    public void visit(Page page) {
        if(SomeCriteria())
        {
            //make all other crawlers stop until I finish
            SingleThread();
            //let them resume
        }

        //Normal Stuff
    }
   }
您可以使用wait()和notify()

线程等待:

  // define mutex as field
  Object mutex = new Object();

   // later:
   synchronized(mutex) {
        wait();
   }
通知线程继续

   synchronized (mutex) {
        notify();
   }
调用
\u resume
\u suspend
将使您能够继续并暂停
线程<代码>\u stop
将允许您优雅地停止线程。请注意,一旦停止
线程
,就无法再次恢复。
线程
不再可用


这段代码来自一个真实的开源项目:

下面是一个简短的示例,介绍如何使用酷炫的java并发技术实现这一点:

剪断旧代码对于Pause类不再重要

编辑:

以下是新的测试类:

package de.hotware.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {

    private Pause mPause;

    public Test() {
        this.mPause = new Pause();
    }

    public void concurrent() throws InterruptedException {
        while(true) {
            this.mPause.probe();
            System.out.println("concurrent");
            Thread.sleep(100);
        }
    }

    public void crucial() throws InterruptedException {
        int i = 0;
        while (true) {
            if (i++ % 2 == 0) {
                this.mPause.pause(true);
                System.out.println("crucial: exclusive execution");
                this.mPause.pause(false);
            } else {
                System.out.println("crucial: normal execution");
                Thread.sleep(1000);
            }
        }
    }

    public static void main(String[] args) {
        final Test test = new Test();
        Runnable run = new Runnable() {

            @Override
            public void run() {
                try {
                    test.concurrent();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        };
        Runnable cruc = new Runnable() {

            @Override
            public void run() {
                try {
                    test.crucial();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        };
        ExecutorService serv = Executors.newCachedThreadPool();
        serv.execute(run);
        serv.execute(run);
        serv.execute(cruc);
    }

}
和实用程序暂停类:

package de.hotware.test;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Utility class to pause and unpause threads
 * with Java Concurrency
 * @author Martin Braun
 */
public class Pause {

    private Lock mLock;
    private Condition mCondition;
    private AtomicBoolean mAwait;

    public Pause() {
        this.mLock = new ReentrantLock();
        this.mCondition = this.mLock.newCondition();
        this.mAwait = new AtomicBoolean(false);
    }

    /**
     * waits until the threads until this.mAwait is set to true
     * @throws InterruptedException
     */
    public void probe() throws InterruptedException {
        while(this.mAwait.get()) {
            this.mLock.lock();
            try {
                this.mCondition.await();
            } finally {
                this.mLock.unlock();
            }
        }
    }

    /**
     * pauses or unpauses
     */
    public void pause(boolean pValue) {
        if(!pValue){
            this.mLock.lock();
            try {
                this.mCondition.signalAll();
            } finally {
                this.mLock.unlock();
            }
        }
        this.mAwait.set(pValue);
    }

}
基本用法是在每次运行之前调用probe()。如果在调用pause(false)之前暂停,则此操作将被阻止

您的类将如下所示:

private void Concurrent() {
    if (shouldRun()) {
        // notify threads to pause and wait for them
        DoJob();
        // resume threads
    }

    // Normal job...
}
public class TestCrawler extends WebCrawler {

private Pause mPause;

public TestCrawler(Pause pPause) {
    this.mPause = pPause;
}

private SingleThread()
{
        //When this function is running, no other crawler should do anything
}

@Override
public void visit(Page page) {
    if(SomeCriteria())
    {
        //only enter the crucial part once if it has to be exclusive
        this.mPause.probe();
        //make all other crawlers stop until I finish
        this.mPause.pause(true);
        SingleThread();
        //let them resume
        this.mPause.pause(false);
    }
    this.mPause.probe();
    //Normal Stuff
}
}

你能给我举个简单的例子吗?谢谢。我注意到你正在自己创建线程。我不能那样做。我已经更新了我的问题。那么我怎么能做类似的事情呢?@AlirezaNoori我们能做这个吗?创建一个
守护进程线程
,然后让其他线程加入它?我想我对我的问题解释得不够好。请阅读第二次更新。我认为这会澄清问题。您是否考虑过改用
阻塞队列
?线程只有通过向其添加代码来停止,才能停止。你不能在外部安全地停止/暂停线程。好的,这里有很多东西。你确定我的案子需要这些吗?请您阅读我的最新更新,并告诉我如何修改我的代码。在您的情况下,并发(…)与访问是一样的。关键(…)与单线程(…)相同。我不知道这个框架,但是如果你有一个以上的类实例,你可能需要把一个对象传递给所有的类,它们可以锁定。但让我来做点什么我用了你的密码。经过几次测试,效果良好。然而,当我在实际情况下测试时,似乎有一些错误。它就像:
Crawler1->Probe Crawler2->Probe Crawler3->Probe…
你能帮帮忙吗?谢谢。你使用的是我修改过的类代码吗?您可能必须使SomeCriteria()方法线程安全。我认为您的一般问题是多个线程成为独占线程。您必须使此部件线程安全,并且不会出现死锁。基本上,你需要做的是创建一个“原子”块,在其中你获得了许可,一旦你获得了许可,就让其他人得不到许可。这可以通过AtomicBoolean和getAndSet(值)实现。这将检索是否允许您获得作为独占线程的权限,然后将其设置为false(因此它已被接受)。但是有了这一点,当你把它设置为真的时候,你必须关心比赛条件。