Thread和Runnable之区别(售票系统)
两种方式有什么不同,利用Runnable可以实现资源共享:
一、售票系统用Thread进行实现如下:
public class TicketThread extends Thread {
private int ticket = 5;// 总共5张票
@Override
public void run() {
while (true)
if (ticket > 0)
System.out.println(Thread.currentThread().getName() + ":正在卖第" + ticket-- + "张票 ... ... ");
}
public static void main(String[] args) {
// 创建3个线程
TicketThread tt1 = new TicketThread();
TicketThread tt2 = new TicketThread();
TicketThread tt3 = new TicketThread();
// 启动线程
tt1.start();
tt2.start();
tt3.start();
}
}
运行结果如下:
Thread-2:正在卖第5张票 ... ...
Thread-2:正在卖第4张票 ... ...
Thread-2:正在卖第3张票 ... ...
Thread-2:正在卖第2张票 ... ...
Thread-2:正在卖第1张票 ... ...
Thread-0:正在卖第5张票 ... ...
Thread-0:正在卖第4张票 ... ...
Thread-0:正在卖第3张票 ... ...
Thread-0:正在卖第2张票 ... ...
Thread-0:正在卖第1张票 ... ...
Thread-1:正在卖第5张票 ... ...
Thread-1:正在卖第4张票 ... ...
Thread-1:正在卖第3张票 ... ...
Thread-1:正在卖第2张票 ... ...
Thread-1:正在卖第1张票 ... ...
一共5张票,实际执行结果却是卖了15张票。从中可以看出使用Thread不能够实现数据共享的效果。
二、售票系统用Runnable进行实现如下:
public class TicketRunnable implements Runnable {
private int ticket = 5;// 总共5张票
@Override
public void run() {
while (true)
if (ticket > 0)
System.out.println(Thread.currentThread().getName() + ":正在卖第" + ticket-- + "张票 ... ... ");
}
public static void main(String[] args) {
// 利用实例化一个Runnable对象,实现共享
TicketRunnable tr = new TicketRunnable();
// 创建3个线程
Thread tt1 = new Thread(tr, "1号窗户");
Thread tt2 = new Thread(tr, "2号窗户");
Thread tt3 = new Thread(tr, "3号窗户");
// 启动线程
tt1.start();
tt2.start();
tt3.start();
}
}
运行结果如下:
1号窗户:正在卖第5张票 ... ...
3号窗户:正在卖第3张票 ... ...
2号窗户:正在卖第4张票 ... ...
3号窗户:正在卖第1张票 ... ...
1号窗户:正在卖第2张票 ... ...
一共5张票,实际执行结果也是卖了5张票。从中可以看出使用Runnable能够实现数据共享的效果。
利用实例化一个Runnable对象,实现共享。
三、通过只实例化一个Runnable对象来进行共享资源。
需求:主线程和子线程都是并发执行的,也就是当子线程在执行的过程中,主线程也在往下执行。主线程需要所有子线程返回执行结果才能继续执行。
我们利用一个CountDownLatch来实现。
CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
主要方法
public CountDownLatch(int count);
public void countDown();
public void await() throws InterruptedException
构造方法参数指定了计数的次数
countDown方法,当前线程调用此方法,则计数减一
awaint方法,调用此方法会一直阻塞当前线程,直到计时器的值为0
实例如下:import java.util.concurrent.CountDownLatch;
public class MyRunnableReturn implements Runnable {
private CountDownLatch threadsSingal;
public MyRunnableReturn(CountDownLatch threadsSingal) {
super();
this.threadsSingal = threadsSingal;
}
public void run() {
System.out.println(Thread.currentThread().getName() + "--开始");
System.out.println(Thread.currentThread().getName() + "--结束");
threadsSingal.countDown();// 线程减1
}
public static void main(String[] agrs) {
System.out.println("Main --开始");
CountDownLatch threadsSingal = new CountDownLatch(3);
MyRunnableReturn myRunnable = new MyRunnableReturn(threadsSingal);
new Thread(myRunnable, "thread1").start();
new Thread(myRunnable, "thread2").start();
new Thread(myRunnable, "thread3").start();
try {
threadsSingal.await();// 等待所有子线程执行完
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main --结束");
}
}
运行结果如下:
Main --开始
thread1--开始
thread1--结束
thread3--开始
thread3--结束
thread2--开始
thread2--结束
Main --结束
综上实例可以看出,达到了需求的效果。先执行所有子线程,再运行主线程。