多线程(多窗口卖票例子)

实现多线程的方式:

实现多线程的方式有多种,这里只列举两种常用的,而第一种继承Thread的方式无法实现多窗口卖票。

一,继承Thread方式:

特点:多线程多实例,无法实现资源的共享。

例子:

 1package com.demo.study.multithreading;
 2 3publicclass MyThread extends Thread{
 4 5privateint i = 10;
 6// 可以自行定义锁,也可以使用实例的锁 7     Object mutex = new Object();
 8publicvoid selltickets(){
 910synchronized (mutex) {
1112if(i>0){
13             i--;
14//getName()获取线程的名字15             System.out.println(Thread.currentThread().getName()+" :"+ i);
16        }
17      }
18    }
1920    @Override
21publicvoid run() {
22while(i>0){
2324            selltickets();
25        }
26        }
27 }

启动线程:

 1package com.demo.study.multithreading;
 2 3publicclass Test {
 4 5publicstaticvoid main(String[] args) {
 6//继承Thread方式:多线程多实例,无法实现资源的共享 7         MyThread myThread1 = new MyThread();
 8         MyThread myThread2 = new MyThread();
 9//给线程命名10         myThread1.setName("线程1");
11         myThread2.setName("线程2");
12        myThread1.start();
13        myThread2.start();
14    }
15 }

运行结果:

二,实现Runnable方式:

特点:多线程单实例,可实现资源的共享

例子:实现多窗口卖票:

 1package com.demo.study.multithreading;
 2 3publicclass MyThreadImpl implements Runnable {
 4 5privateint tickets = 10;
 6 7publicvoid sellTickets() {
 8 9synchronized (MyThreadImpl.class) {
10if (tickets > 0) {
1112             tickets--;
13             System.out.println(Thread.currentThread().getName() + "正在卖票,还剩下" + tickets + "张");
14            }
15        }
16    }
1718    @Override
19publicvoid run() {
2021while (tickets > 0) {
22            sellTickets();
23try {
24// 休眠一秒,让执行的效果更明显25                 Thread.sleep(100);
26             } catch (InterruptedException e) {
27                e.printStackTrace();
28            }
29        }
30    }
31 }

启动线程:

注意:线程的启动是通过Thread中的start()方法,而线程的启动,只运行了实例类中的重写的run()方法。
void`start)()使该线程开始执行;Java 虚拟机调用该线程的run` 方法。
1package com.demo.study.multithreading;
2 3publicclass Test {
4 5publicstaticvoid main(String[] args) {
6 7//只创建一个实例 8 MyThreadImpl threadImpl = new MyThreadImpl();
9//将上面创建的唯一实例放入多个线程中,Thread类提供了多个构造方法,见下图(构造方法摘要)10 Thread thread1 = new Thread(threadImpl, “窗口1”);
11 Thread thread2 = new Thread(threadImpl, “窗口2”);
12 thread1.start();
13 thread2.start();
1415 }
16 }

运行结果:

三、同步锁与资源共享:

执行synchronized部分代码的时候必须需要对象锁,而一个对象只有一个锁,只有执行完synchronized里面的代码后释放锁,其他线程才可以获得锁,那么就保证了同一时刻只有一个线程访问synchronized里面的代码。实现资源共享的关键是,只有一个实例,synchronized使用的是同一把锁,用实例的锁或者定义一个实例。这就需要使用实现Runnable接口的方式,实现多线程,这样传入的是一个实例。继承Thread的方式,传入的是多个实例,每个实例都有一个锁,那就无法实现控制。