创建线程的第一种方式:
- 创建一个类继承Thread
- 重写Thread中的run方法 (创建线程是为了执行任务 任务代码必须有存储位置,run方法就是任务代码的存储位置。)
- 创建子类对象,其实就是在创建线程
- 启动线程start()
这种方式的特点(缺陷):线程任务和线程是绑定在一起的。
示例:
四个窗口同时卖票,
因为是同时,所以使用多线程。
创建四个线程,都是卖票。
因为都是卖票,所以四个线程的任务是一样的。
只需要定义一个类继承Thread。
1 class Ticket extends Thread 2 { 3 private static int num = 50; //定义成static,四个线程共享50张票。 4 public void run() 5 { 6 while(num>0) 7 System.out.println(Thread.currentThread().getName()+"...sale..."+num--); 8 } 9 } 10 11 class Maipiao 12 { 13 public static void main(String[] args) 14 { 15 Ticket win1 = new Ticket(); 16 Ticket win2 = new Ticket(); 17 Ticket win3 = new Ticket(); 18 Ticket win4 = new Ticket(); 19 20 win1.start(); 21 win2.start(); 22 win3.start(); 23 win4.start(); 24 } 25 }
为了解决四个线程共享票的问题,需要使用创建线程的第二种方式:
- 创建实现了Runnable接口的子类
- 重写Runnable接口中的run方法
- 创建实现了Runnable接口的子类的对象
- 创建Thread类的对象,也就是在创建线程
- 把实现了Runnable接口的子类对象作为参数传递给Thread类的构造方法
这种方式的特点是:把线程任务进行了描述,也就是面向对象,从而实现了线程任务和线程对象的分离。线程执行什么任务不再重要,只要是实现了Runnable接口的子类对象都可以作为参数传递给Thread的构造方法,此方式较为灵活。
第二种方式还有一个好处是实现接口了,还不影响继承其他父类。
1 //这个类只是为了描述线程的任务,跟线程没有任何关系。 2 class Ticket implements Runnable 3 { 4 private int num = 50; 5 public void run() 6 { 7 while(num>0) 8 System.out.println(Thread.currentThread().getName()+"...sale..."+num--); 9 } 10 } 11 12 class Maipiao 13 { 14 public static void main(String[] args) 15 { 16 Ticket t = new Ticket(); 17 18 Thread win1 = new Thread(t); 19 Thread win2 = new Thread(t); 20 Thread win3 = new Thread(t); 21 Thread win4 = new Thread(t); 22 23 win1.start(); 24 win2.start(); 25 win3.start(); 26 win4.start(); 27 } 28 }
总结:为什么创建线程的第二种方式可以解决卖票问题?
第一种创建线程的方式:线程和线程任务是绑定在一起的,创建了4个线程就创建了4份资源。
第二种创建线程的方式:线程和线程任务进行了分离,只需要创建一个任务,让4个线程分别去执行。