Java:同步ScheduledExecutorService上的两个调度线程

Java:同步ScheduledExecutorService上的两个调度线程,java,multithreading,thread-synchronization,scheduledexecutorservice,Java,Multithreading,Thread Synchronization,Scheduledexecutorservice,我想创建一个程序: 做一个长时间运行的任务,比如说ChildJob 暂停主要任务ChildJob,并每隔几秒钟提交完成的工作 我提出了这段代码,它安排了两个线程,每几秒钟提交一次提交部分目前是一个sop语句,并且并行运行ChildJob 我面临的问题是,我无法正确地同步这两个线程 在调用commit时,ChildJob线程将继续处理。如何让ChildJob线程等待? 我理解使进程方法同步不是一个选项,因为在这种情况下,提交作业甚至不会运行 import java.util.concurrent.

我想创建一个程序:

做一个长时间运行的任务,比如说ChildJob 暂停主要任务ChildJob,并每隔几秒钟提交完成的工作 我提出了这段代码,它安排了两个线程,每几秒钟提交一次提交部分目前是一个sop语句,并且并行运行ChildJob

我面临的问题是,我无法正确地同步这两个线程

在调用commit时,ChildJob线程将继续处理。如何让ChildJob线程等待? 我理解使进程方法同步不是一个选项,因为在这种情况下,提交作业甚至不会运行

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.Random;
import java.util.Date;


class Main {

    // Processing thread, commiting thread
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

    public static void main(String[] args) {

        Main app = new Main();
        ChildJob workUnit = new ChildJob();

        Thread childJobThread = new Thread(new Runnable() 
        { 
            @Override
            public void run() 
            { 
                System.out.println("childJobThread: "+ Thread.currentThread().getName()+" Start. Time = " + new Date());
                try{ workUnit.process(); }
                catch(InterruptedException e){ e.printStackTrace(); } 
            } 
        }); 
        Thread committerThread = new Thread(new Runnable() 
        { 
            @Override
            public void run() 
            { 
                try{ workUnit.commit();  }
                catch(InterruptedException e){ e.printStackTrace(); } 
            } 
        }); 

        final ScheduledFuture<?> commitHandle = app.scheduler.scheduleAtFixedRate(committerThread, 1, 8, TimeUnit.SECONDS);
        final ScheduledFuture<?> jobHandle = app.scheduler.schedule(childJobThread, 0, TimeUnit.SECONDS);
        /*
        Makes the commitHandle run for 60 * 60 seconds, not needed, manually terminating currently.
        app.scheduler.schedule(new Runnable() {
                public void run() {
                    commitHandle.cancel(true);
                }
            }, 
            60 * 60, TimeUnit.SECONDS);*/
    }
}

class ChildJob {
    private int i = 0;

    public void process() throws InterruptedException 
    { 

         // synchronized(this) 
         // {   
            while(true) {
                System.out.println("ChildJob processing at: " + Thread.currentThread().getName() + " : " + new Date() + "----------: " + i++);
                Thread.sleep(1000);
            }
        //} 
    } 

    public void commit() throws InterruptedException 
    {   
        synchronized(this) 
        { 
            System.out.println("\ncommitterThread: " + Thread.currentThread().getName()+" Start. Time = " + new Date());
            // 3s sleep to check consistency from processing.
            Thread.sleep(3000);
            System.out.println("committerThread: " + Thread.currentThread().getName()+"     End. Time = " + new Date() + "\n");
        } 
    } 
}
预期结果:

childJobThread: pool-1-thread-1 Start. Time = Mon May 13 17:51:31 IST 2019
ChildJob processing at: pool-1-thread-1 : Mon May 13 17:51:31 IST 2019----------: 0

committerThread: pool-1-thread-2 Start. Time = Mon May 13 17:51:32 IST 2019
committerThread: pool-1-thread-2     End. Time = Mon May 13 17:51:35 IST 2019

ChildJob processing at: pool-1-thread-1 : Mon May 13 17:51:35 IST 2019----------: 1
ChildJob processing at: pool-1-thread-1 : Mon May 13 17:51:36 IST 2019----------: 2
ChildJob processing at: pool-1-thread-1 : Mon May 13 17:51:37 IST 2019----------: 3
ChildJob processing at: pool-1-thread-1 : Mon May 13 17:51:38 IST 2019----------: 4
ChildJob processing at: pool-1-thread-1 : Mon May 13 17:51:39 IST 2019----------: 5

committerThread: pool-1-thread-2 Start. Time = Mon May 13 17:51:40 IST 2019
committerThread: pool-1-thread-2     End. Time = Mon May 13 17:51:43 IST 2019

ChildJob processing at: pool-1-thread-1 : Mon May 13 17:51:44 IST 2019----------: 6
ChildJob processing at: pool-1-thread-1 : Mon May 13 17:51:45 IST 2019----------: 7
ChildJob processing at: pool-1-thread-1 : Mon May 13 17:51:46 IST 2019----------: 8
ChildJob processing at: pool-1-thread-1 : Mon May 13 17:51:47 IST 2019----------: 9
ChildJob processing at: pool-1-thread-1 : Mon May 13 17:51:48 IST 2019----------: 10
同时尝试同步,例如:

whiletrue{ 同步这个 { System.out.printlnChildJob处理地址:+Thread.currentThread.getName+:+新日期+------:+i++; 线程1000; } } } 我们的想法是,委员会应该有机会进入工作的运行

样本输出

childJobThread: pool-1-thread-1 Start. Time = Mon May 13 20:42:46 CST 2019
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:46 CST 2019----------: 0
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:47 CST 2019----------: 1
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:48 CST 2019----------: 2
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:49 CST 2019----------: 3
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:50 CST 2019----------: 4
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:52 CST 2019----------: 5
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:53 CST 2019----------: 6

committerThread: pool-1-thread-2 Start. Time = Mon May 13 20:42:54 CST 2019
committerThread: pool-1-thread-2     End. Time = Mon May 13 20:42:57 CST 2019

ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:57 CST 2019----------: 7
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:58 CST 2019----------: 8
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:59 CST 2019----------: 9
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:00 CST 2019----------: 10
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:01 CST 2019----------: 11

committerThread: pool-1-thread-2 Start. Time = Mon May 13 20:43:02 CST 2019
committerThread: pool-1-thread-2     End. Time = Mon May 13 20:43:05 CST 2019

ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:05 CST 2019----------: 12
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:06 CST 2019----------: 13
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:07 CST 2019----------: 14
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:08 CST 2019----------: 15
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:09 CST 2019----------: 16
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:10 CST 2019----------: 17
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:11 CST 2019----------: 18
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:12 CST 2019----------: 19
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:13 CST 2019----------: 20
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:14 CST 2019----------: 21
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:15 CST 2019----------: 22
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:16 CST 2019----------: 23

为什么要暂停线程并从另一个线程提交?您只需从ChildJob线程进行提交即可—更简单、更可靠。因为,我需要使提交事件基于时间保持一致。比如说,每n秒。而ChildJob.process方法可以根据处理量进行放大或缩小,因此在代码中没有可以放置提交代码的地方。我正在尝试实现一种检查点/自动保存功能。这根本不起作用。更好的方法是使用内置原语,如可重入锁、condvars、锁存器等。但是,通过在一个线程中执行所有操作,完全避免同步问题更好。多线程的好处是可以进行并行处理。如果同步并序列化处理,只会增加复杂性并失去好处。因此这是毫无意义的。@SvetlinZarev抱歉,我不太确定“根本不起作用”部分。在我的笔记本电脑上运行良好,“提交”在“作业”运行之间运行,“提交”期间没有“作业”运行。我认为这绝对是OP想要的。一个周期性地解锁然后立即再次锁定的循环会导致线程饥饿。@SolomonSlow我承认这不是解决这个问题的最佳方案,但它是有效的。我还认为这种简单的方法有助于OP理解这一点,这是一种选择。基于时间的解决方案本质上是不可靠的。想象一下,您在快速服务器类机器和raspberry pi上运行相同的应用程序。在服务器上,它每秒可以处理100k个元素,但在ePi上,它每秒可以处理少于1个元素。您看到基于时间的提交的问题了吗?此外,如果计时器线程因RuntimeException而失败,它将永远不会被重新调度,因此它将永远不会调用commmit
childJobThread: pool-1-thread-1 Start. Time = Mon May 13 20:42:46 CST 2019
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:46 CST 2019----------: 0
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:47 CST 2019----------: 1
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:48 CST 2019----------: 2
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:49 CST 2019----------: 3
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:50 CST 2019----------: 4
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:52 CST 2019----------: 5
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:53 CST 2019----------: 6

committerThread: pool-1-thread-2 Start. Time = Mon May 13 20:42:54 CST 2019
committerThread: pool-1-thread-2     End. Time = Mon May 13 20:42:57 CST 2019

ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:57 CST 2019----------: 7
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:58 CST 2019----------: 8
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:42:59 CST 2019----------: 9
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:00 CST 2019----------: 10
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:01 CST 2019----------: 11

committerThread: pool-1-thread-2 Start. Time = Mon May 13 20:43:02 CST 2019
committerThread: pool-1-thread-2     End. Time = Mon May 13 20:43:05 CST 2019

ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:05 CST 2019----------: 12
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:06 CST 2019----------: 13
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:07 CST 2019----------: 14
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:08 CST 2019----------: 15
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:09 CST 2019----------: 16
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:10 CST 2019----------: 17
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:11 CST 2019----------: 18
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:12 CST 2019----------: 19
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:13 CST 2019----------: 20
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:14 CST 2019----------: 21
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:15 CST 2019----------: 22
ChildJob processing at: pool-1-thread-1 : Mon May 13 20:43:16 CST 2019----------: 23