如何确保同一线程不会在代码块中重新输入

时间:2019-04-02 09:22:24

标签: java multithreading concurrency console

我正在用Java控制台应用程序制作类似Web爬网程序的东西,我得到了一个实现可运行接口的类,并且在方法运行中,我得到了我想做的操作(例如一个for循环,该循环迭代每个URL作为输入并在所有计算中进行)。

我希望每个迭代都由不同的线程完成。因此,我使用executorsservice(线程数与url数相同)创建了一个线程池,并使用了synced关键字,一次只允许一个线程在其中执行计算块。

但是如何确保同一线程不会再次在代码块内重新进入?如果需要的话,我会在稍后发布代码段。

谢谢。

我得到的输出如下:

我正在用每个URL搜索2个关键字。这个例子是1个网址和2个关键字。

当前线程:pool-1-thread-2 ----------------- 当前线程:pool-1-thread-1 -----------------

标题:维基百科,免费的百科全书 网址:https://en.wikipedia.org Times关键字“免费找到”:41

标题:维基百科,免费的百科全书 网址:https://en.wikipedia.org Times关键字“免费找到”:41

标题:维基百科,免费的百科全书 网址:https://en.wikipedia.org 找到Times关键字Wikibooks:82

标题:维基百科,免费的百科全书 网址:https://en.wikipedia.org 找到Times关键字Wikibooks:82

我认为我以某种方式做到了,但是现在我面临着新的问题,例如请参阅运行方法内的注释。

        public class KeywordCounter {

        private List keylist;
        private List weblist;

        public KeywordCounter(List keywordlist, List listWebsites) {
            this.keylist = new ArrayList(keywordlist);
            this.weblist = new ArrayList(listWebsites);

        }

        public void threadCreate(List klist, List listWebsites) {

            // TODO Auto-generated method stub

            ExecutorService executor = Executors.newFixedThreadPool(2);


            for (int w = 0; w < this.weblist.size(); w++) {

                executor.execute(new Runnable() {

                    private List keylist = new ArrayList(klist);
                    private List weblist = new ArrayList(listWebsites);

                    @Override
                    public synchronized void run() {
System.out.println("Current Thread: " + Thread.currentThread().getName().toString() + " ")

// Computations i want one thread inside here each time but i think both threads are entering same time cause i saw 4 results instaid of 2.
//Also i want inside here to pass the w variable of the for loop, cause i need it for further computations how i can achieve this?.

                });

            }

        }
    }

3 个答案:

答案 0 :(得分:0)

在编写一些代码之前,很难说,但您的方法正确。也尝试使用BlockingQueue。如果您有多个线程,并且队列中每个线程都同时工作,则可以确定它不会是循环。 当然,如果您的线程1在1毫秒内工作,线程2在1分钟内工作,那么...没有任何阻塞。

尝试使用wait/notify also

答案 1 :(得分:0)

“关键部分”

如果您有两个URL,那么您将有两个线程。一个线程用于一个URL,另一个线程用于另一个URL。两者是同时启动的。

现在,我们有一段代码必须不能并行执行,而所有其他代码必须并行执行。这段代码必须被执行!我们将这段代码称为“关键部分”。

“已同步”关键字

要在Java中将某个部分标记为关键,可以使用synced语句:

01 mulithread-code
02 mulithread-code
03 mulithread-code
04 synchronized {
05   critical code
06   critical code
07 }
08 mulithread-code
09 mulithread-code
10 mulithread-code

有两个线程,加入行04的第一个线程将立即启动。第二个线程将等待。第一个线程将完成从第05行到第06行的所有工作。

然后魔术发生了:第一个线程离开行07时,第二个线程停止了等待并继续他的工作:第二个线程将开始执行05行,然后执行{{1 }}。

答案 2 :(得分:0)

 import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Client2 {

    public static void main(String[] args) {


        ExecutorService pool= Executors.newFixedThreadPool(5);
        ExecutorCompletionService<String> completionService = new ExecutorCompletionService<String>(pool);

        List<String> url=Arrays.asList("www.goole.in","www.abc.com");
        for(int i=0;i<url.size();i++) {
        completionService.submit(new MyCallable(url.get(i)));
        }

        for(int i=0;i<url.size();i++) {
        try {
            Future<String> s=completionService.take();
            System.out.println(s.get());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        }
    }

}

 class MyCallable implements Callable<String>{

    String Url;
    public MyCallable(String url) {
        this.Url=url;
    }

    @Override
    public String call() throws Exception {
    //process the URL
        return Url+" Processed.";
    }

}