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();//唤醒在此对象监视器上等待的单个线程。 } }
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(); } }
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(); } } } }