火车站售票案列:
及extends Thread 与 implements Runnable 的区别
加入线程池,提高线程的复用性
package cn.xinking;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//测试:多线程售票
//需求:4个窗口,100张票
public class TrainMyTicket2 {
public static void main(String[] args) {
MyTickets ticket = new MyTickets();
//创建线程池
ExecutorService pool=Executors.newFixedThreadPool(4);
for (int i = 0; i < 4; i++) {//利用4个线程执行同一个任务
//new Thread(ticket).start();
//线程池:线程复用高+托管
//利用池里的线程执行目标任务
pool.execute(ticket);
}
}
}
package cn.xinking;
//测试:多线程售票
//需求:4个窗口,100张票
public class TrainMyTicket2 {
public static void main(String[] args) {
MyTickets ticket = new MyTickets();
for (int i = 0; i < 4; i++) {//利用4个线程执行同一个任务
new Thread(ticket).start();
}
}
}
/**
* 创建步骤:
* 1. 自定义一个类实现Runnable接口。
* 2. 实现Runnable接口 的run方法,把自定义线程的任务定义在run方法上。
* 3. 创建Runnable实现类对象。
* 4. 创建Thread类 的对象,并且把Runnable实现类的对象作为实参传递。
* 5. 调用Thread对象 的start方法开启一个线程。
*
* 注意:
* Runnable实现类的对象并 不是一个线程对象,只不过是实现了Runnable接口的对象而已。
* 只有是Thread或者是Thread的子类才是线程对象。
*/
class MyTickets implements Runnable{
int tickets=100;
@Override
public void run() {
while (true){
//给代码块枷锁,实现同步代码块,实现了访问代码块要排队的效果,没有了超售,重售的现象
synchronized (this){//锁在哪:从同享资源被第一次使用开始,到用完结束
//锁的对象是谁:可以任意,但必须是同一个对象
if(tickets>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"=="+tickets--);
}else {
break;
}
}
}
}
}
package cn.xinking;
public class TrainMyTicket {
public static void main(String[] args) {
for (int i = 0; i < 4; i++) {
new MyTicket().start();//启动线程
}
}
}
/**
* 通过继承Thread类创建线程
*
* (1).首先定义一个类去继承Thread父类,重写父类中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。
* (2).直接创建一个ThreadDemo2类的对象,也可以利用多态性,变量声明为父类的类型。
*
* (3).调用start方法,线程t启动,隐含的调用run()方法。
*/
class MyTicket extends Thread{
static int tickets=100;
@Override
public void run() {
while (true){
synchronized (MyTicket.class){
if(tickets>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(super.getName()+"=="+tickets--);
}else {
break;
}
}
}
}
}