条件满足时停止两个线程

时间:2016-04-29 09:02:44

标签: java android multithreading broadcastreceiver android-broadcastreceiver

我想要执行以下操作:2个线程执行相同的Runnable对象。他们将生成一个随机数。将数字写入日志。如果数字可以被7分割,则停止两个线程并且发送广播,并且广播接收器使用新标签将最终号码放在日志上。我尝试了interrupt()和volatile,但由于某种原因,两个线程中的一个会在停止之前运行一个额外的循环。

public boolean onKeyDown(int keyCode, KeyEvent event) {

    progDailog = ProgressDialog.show(this, "Progress dialog",
            "Working....", true);
    Thread one = new Thread(background, "first");
    one.start();

        Thread two = new Thread(background, "second");
        two.start();

    return true;
}//

    Runnable background = new Runnable() {
        public void run() {

                while (num1 % 7 != 0 && num % 7 != 0) {

                        try {
                            // just doing some long operation
                            Thread.sleep(1000);
                            Random rand = new Random();
                            num = rand.nextInt(9000) + 1000;
                            name = Thread.currentThread().getName();
                            tag = "before";
                            Log.e(tag, name + ":" + num);
                            if (num % 7 == 0) {
                                num1 = num;
                            }
                        } catch (InterruptedException e) {
                        } finally {
                            handler.sendEmptyMessage(0);
                            progDailog.dismiss();
                        }
                } ;
                Intent myObserverSender = new Intent(
                        "action.GO");
                msg = name + ":" + num;
                myObserverSender.putExtra("serviceData", msg);
            sendBroadcast(myObserverSender);
        }

    };

public class MyMainLocalReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context localContext, Intent callerIntent) {
        String serviceData = callerIntent.getStringExtra("serviceData");
        tag = "after";
        Log.e (tag, serviceData);
    }
}

这是最终结果

before: first:7877

before: second:9165

before: first:6760

before: second:5663

After: second:5663 <<<< should stop here

before: first:8025 >>>> this's the extra loop

After: first:5663 >>> wrong

顺便问一下,我做的广播是否正确?

1 个答案:

答案 0 :(得分:0)

我创建了一个停止线程的简化版本。这是它的工作原理:

  1. 主线程创建一个停止其他线程的命令。
  2. 主线程存储对要停止的线程的引用
  3. 主线程为线程提供了stop命令,以便他们可以在需要时调用它
  4. stop命令使用AtomicBoolean来确保它只停止有问题的线程一次。
  5. 我捎带了interrupt()方法上的线程停止逻辑。
  6. 所以,这是完整的代码:

    package com.example;
    
    import java.util.List;
    import java.util.Random;
    import java.util.concurrent.CopyOnWriteArrayList;
    import java.util.concurrent.atomic.AtomicBoolean;
    
    public class Main {
    
        public static void main(String[] args) {
            final List<Thread> threads = new CopyOnWriteArrayList<>();
            final AtomicBoolean stopping = new AtomicBoolean(false);
            Runnable stopCommand = () -> {
                if (!stopping.getAndSet(true)) {
                    for (Thread thread : threads) {
                            thread.interrupt();
                    }
                }
            };
            Background background = new Background(stopCommand);
            Thread t1 = new Thread(background);
            Thread t2 = new Thread(background);
            threads.add(t1);
            threads.add(t2);
            t1.start();
            t2.start();
    
        }
    
        private static class Background implements Runnable {
    
            private Runnable stopCommand;
    
            public Background(Runnable stopCommand) {
                this.stopCommand = stopCommand;
            }
    
            @Override
            public void run() {
                Random rand = new Random();
                String name = Thread.currentThread().getName();
                while (!Thread.currentThread().isInterrupted()) {
                    int num = rand.nextInt(9000) + 1000;
                    System.out.println(name + ", num: " + num);
                    if ((num % 7) == 0) {
                        stopCommand.run();
                    }
                }
                System.out.println(name + " interrupted. Stopping.");
            }
    
        }
    
    }
    

    您也可以使用执行程序来代替自己使用列表:

    package com.example;
    
    import java.util.Random;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Main {
    
        public static void main(String[] args) {
            final ExecutorService ex = Executors.newFixedThreadPool(2);
            Runnable stopCommand = () -> {
                System.out.println("stopping");
                ex.shutdownNow();
            };
            Background background = new Background(stopCommand);
            ex.submit(background);
            ex.submit(background);
        }
    
        private static class Background implements Runnable {
    
            private Runnable stopCommand;
    
            public Background(Runnable stopCommand) {
                this.stopCommand = stopCommand;
            }
    
            @Override
            public void run() {
                Random rand = new Random();
                String name = Thread.currentThread().getName();
                while (!Thread.currentThread().isInterrupted()) {
                    int num = rand.nextInt(9000) + 1000;
                    System.out.println(name + ", num: " + num);
                    if ((num % 7) == 0) {
                        stopCommand.run();
                    }
                }
                System.out.println(name + " interrupted. Stopping.");
            }
    
        }
    
    }