• 八、多线程基础-如何控制多线程执行顺序经典示例3


    1、子线程运行执行 10 次后,主线程再运行 5 次,这样交替执行三遍

    package threadLearning.threadAlternates;
    public class Bussiness {
        private boolean subFlag = true;//主线程和子线程切换的控制开关
        public static void main(String[] args) {
            final Bussiness bussiness = new Bussiness();
            // 子线程
            new Thread(new Runnable() {
                public void run() {
                    for (int i = 0; i < 3; i++) {
                        bussiness.subMethod();
                    }
                }
            }).start();
            // 主线程
            for (int i = 0; i < 3; i++) {
                bussiness.mainMethod();
            }
        }
        public synchronized void mainMethod() {
            while (subFlag) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName()
                        + " : main thread running loop count -- " + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            subFlag = true;
            notify();
        }
        public synchronized void subMethod() {
            while (!subFlag) {
                try {
                    wait();//在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (int i = 0; i < 10; i++) {
                System.err.println(Thread.currentThread().getName()
                        + " : sub thread running loop count -- " + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            subFlag = false;
            notify();//唤醒在此对象监视器上等待的单个线程。
        }
    }
    View Code

    2、现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果

    package threadLearning.threadSafeProblem;
    /**
     *
     * @classDesc: 功能描述:需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果。
     * @author: zjb
     * @createTime: 创建时间:2018-6-23 下午11:12:29
     * @version: v1.0
     * @copyright:
     */
    public class ThreadTrain1 implements Runnable {
        private static int count = 100;
        private static Object oj = new Object();
    
        public void run() {
            while (count > 0) {
                try {
                    //Thread.sleep(1000);
                } catch (Exception e) {
    
                }
                sale();
            }
    
        }
        public  void sale() {
            // 前提 多线程进行使用、多个线程只能拿到一把锁。
            // 保证只能让一个线程 在执行 缺点效率降低
            /*如何解决线程同步问题:
              方法1:使用同步代码块,如下;
              方法2:使用同步函数:在方法上修饰synchronized 称为同步函数,如:
             public synchronized void sale()
                思考:同步函数使用this锁。证明方式: 一个线程使用同步代码块(this明锁),另一个线程使用同步函数。
            如果两个线程抢票不能实现同步,那么会出现数据错误。
             */
            synchronized (oj) {
                if (count > 0) {
                    System.out.println(Thread.currentThread().getName() + ",出售第"
                            + (100 - count + 1) + "票");
                    count--;
                }
            }
    
        }
    
    }
    
    package threadLearning.threadSafeProblem;
    /**
     *
     * @classDesc: 功能描述:
     * @author: zjb
     * @createTime: 创建时间:2018-6-23 下午11:24:14
     * @version: v1.0
     * @copyright:
     */
    
    public class ObtainTest1 {
        public static void main(String[] args) {
            ThreadTrain1 threadTrain = new ThreadTrain1();
    
            Thread obtainThread1 = new Thread(threadTrain, "1号窗口");
            Thread obtainThread2 = new Thread(threadTrain, "2号窗口");
            obtainThread1.start();
            obtainThread2.start();
        }
    
    }
    View Code

    3、使用定时器,间隔 4 秒执行一次,再间隔 2 秒执行一次,以此类推执行
    Timer:一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行
          构造方法:
           Timer(String name)
                  创建一个新计时器,其相关的线程具有指定的名称。
           Timer(String name, boolean isDaemon)
                  创建一个新计时器,其相关的线程具有指定的名称,并且可以指定作为守护程序运行。
          方法:
          void schedule(TimerTask task, long delay)
                  安排在指定延迟后执行指定的任务

    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    public class TimerTastCus extends TimerTask {
        private static volatile int count = 1;//确保每个执行器获取到的count值都是最新的
        
        @Override
        public void run() {
    //实现一个值在0和1之前交替取值,进而使得执行器4秒,2秒交替执行
            count = (count + 1) % 2;
            System.err.println("count---》 "+count);
            System.out.println("当前执行线程为-创建对象前->"+Thread.currentThread().getName());
            new Timer().schedule(new TimerTastCus(), 2000+2000*count);
            
        }
    
        public static void main(String args[]) {
            Timer timer = new Timer();
            timer.schedule(new TimerTastCus(), 2000 + 2000 * count);//毫秒
            while (true) {
                try {
                    System.out.println("当前执行线程为-->"+Thread.currentThread().getName()+"   当前时间的秒数:-->"+new Date().getSeconds());
                    Thread.sleep(1000);//
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
    View Code
    细水长流,打磨濡染,渐趋极致,才是一个人最好的状态。
  • 相关阅读:
    delphi 如何让ScrollBox的内容与滚动条一起实时滚动
    C# Wpf集合双向绑定
    C# Wpf异步修改UI,多线程修改UI(二)
    C# 自定义线程修改UI(一)
    WPF FindName()查找命名注册的元素
    数据绑定
    WPF绑定Binding及模式
    WPF-Binding的源
    WPF-Binding对数据的检验
    WPF-数据转换
  • 原文地址:https://www.cnblogs.com/jiarui-zjb/p/9622562.html
Copyright © 2020-2023  润新知