本篇简单的讲下线程的几种创建方式并相应的实现售票功能
一、线程创建
public class ThreadTest {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//线程的三种创建方式
//1继承thread类 重写run方法
createThread thread=new createThread();
thread.start();
//2实现Runnable接口 重写run方法
createThread1 thread1=new createThread1();
Thread thread2=new Thread(thread1);
thread2.start();
//3实现callable接口,重写call方法
createThread2 thred2=new createThread2();
FutureTask<String> ft=new FutureTask<String>(thred2);
new Thread(ft).start();
System.out.println("返回值:"+ft.get());
//4利用ExecutorService线程池来管理线程
ExecutorService threadPool=Executors.newFixedThreadPool(2);
threadPool.execute(thread1);
}
}
//继承thread类
class createThread extends Thread{
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+" i:"+i);
}
}
}
//实现runnable接口
class createThread1 implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+" i:"+i);
}
}
}
//实现callable接口
class createThread2 implements Callable<String>{
@Override
public String call() throws Exception {
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+" i:"+i);
}
return "该方法创建线程有返回值";
}
}
第三种方式是利用了FutureTask类和Callable接口
首先创建Callable接口的实现类,实现call()方法,该方法比run()方法要强大,会有返回值返回。
使用FutureTask类包装Callable对象,创建thread对象,将FutureTask对象传给thrad,调用start()方法开启线程。调用FutureTask对象的get()方法可以获得线程结束后的返回值。
其他三者之间的比较,无非是继承thread类的,获取当前线程可以直接this.getName(),不能再继承其他的类了。
而实现接口的方式获取当前线程必须用Thread.currentThread().getName(),还能够再继承其他的类。
二、基于上面的三种方式实现卖票功能
描述:有四个窗口在买票,总票数为100,每售出一张,打印出窗口号和票的序号。每个窗口命名"窗口1”到"窗口4"
(1)继承thread实现
public static void main(String[] args) {
ticketsWindow tic1=new ticketsWindow();
tic1.setName("窗口1");
ticketsWindow tic2=new ticketsWindow();
tic2.setName("窗口2");
ticketsWindow tic3=new ticketsWindow();
tic3.setName("窗口3");
ticketsWindow tic4=new ticketsWindow();
tic4.setName("窗口4");
tic1.start();
tic2.start();
tic3.start();
tic4.start();
}
}
class ticketsWindow extends Thread{
private static int ticket=100;
private static Object o=new Object();
public void run(){
while(true){
synchronized (o) {
if(ticket>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
ticket--;
System.out.println(getName()+":第"+(100-ticket)+"张票已被售出");
}else{
break;
}
}
}
}
}
(2)实现Runnable接口
public static void main(String[] args) {
ticketsWindows tkw = new ticketsWindows();
Thread s1 = new Thread(tkw, "窗口1");
Thread s2 = new Thread(tkw, "窗口2");
Thread s3 = new Thread(tkw, "窗口3");
Thread s4 = new Thread(tkw, "窗口4");
s1.start();
s2.start();
s3.start();
s4.start();
}
}
class ticketsWindows implements Runnable {
private static int ticket = 100;
@Override
public void run() {
while (true) {
synchronized (this) {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
--ticket;
System.out.println(Thread.currentThread().getName() + " :第"
+ (100 - ticket) + "张票已售出");
} else {
break;
}
}
}
}
(3)利用ExecutorService线程池
public class TicketThread3 {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(4);
Ticket tickT = new Ticket();
for (int i = 1; i < 5; i++) {
Thread thread = new Thread(tickT);
threadPool.execute(thread);
}
}
}
class Ticket implements Runnable {
private static int i = 10;
@Override
public void run() {
while (true) {
synchronized (this) {
if (i > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
--i;
System.out.println(Thread.currentThread().getName() + " :第"
+ (10 - i) + "张票已售出");
} else {
break;
}
}
}
}
}
输出结果: