八、多线程基础-如何控制多线程执行顺序经典示例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

 

posted @ 2018-09-10 20:21  爱笑的berg  阅读(467)  评论(0编辑  收藏  举报