场景
学习多线程编程,写 一个mini售票系统
问题
怎么创建线程,如何模拟售票窗口
实验
模拟3个窗口卖10张票,代码如下:
/**
* Project Name:thinkinginjava
* File Name:ThreadCallable.java
* Package Name:com.sourcecode.java.thread
* Date:2016年2月14日下午10:25:25
* Copyright (c) 2016, 282009375@qq.com All Rights Reserved.
*
*/
package com.sourcecode.java.thread;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* ClassName: ThreadCallable <br/>
* Function: TODO mini 售票系统 <br/>
* Reason: TODO 学习有返回的线程创建方式<br/>
* date: 2016年2月14日 下午10:25:25 <br/>
*
* @author Administrator
* @version 1.0
* @since JDK 1.6
*/
public class ThreadCallable implements Callable<Object>
{
/*
* 线程数-模拟售票窗口
*/
public static int NUM_ThREADS = 3;
/*
* 总票数
*/
public static int TOTAL_TICKETS = 10;
/*
* 总票数
*/
private int ticket;
/**
* Creates a new instance of ThreadCallable.
*
* @param ticket
* 总票数
*/
public ThreadCallable(int ticket)
{
this.ticket = ticket;
}
/**
* TODO 买票 -有返回的线程执行
*
* @see java.util.concurrent.Callable#call()
*/
@Override
public Object call() throws Exception
{
Date end = null;
Date begin = new Date();
while (true)
{
if (ticket > 0)
{
System.out.println("[Window " + Thread.currentThread().getId() + "] is sailing tiket " + ticket--);
Thread.sleep(10);
} else
{
end = new Date();
break;
}
}
long millisTotal = end.getTime() - begin.getTime();
return TOTAL_TICKETS + " tikcets sold in " + millisTotal + " miliseconds.";
}
/**
* TODO 测试.<br/>
*
* @author Administrator
* @param args
* @since JDK 1.6
*/
public static void main(String[] args)
{
//构造一个固定大小的线程池
ExecutorService poor = Executors.newFixedThreadPool(NUM_ThREADS);
//执行结果封装在Future(这名字取得相当有水准啊,大赞)中:
Future<Object> future = poor.submit(new ThreadCallable(TOTAL_TICKETS));
try
{
//是滴,通过get()就能拿到执行结果
System.out.println(future.get().toString());
} catch (Exception e)
{
System.out.println("Sorry,system busy, please try again later!");
}
//释放池资源
poor.shutdown();
}
}
/**
* Project Name:thinkinginjava
* File Name:ThreadRunnable.java
* Package Name:com.sourcecode.java.thread
* Date:2016年2月14日下午11:11:06
* Copyright (c) 2016, 282009375@qq.com All Rights Reserved.
*
*/
package com.sourcecode.java.thread;
import java.util.Date;
/**
* ClassName: ThreadRunnable <br/>
* Function: 模拟3个窗口共卖10张票 <br/>
* Reason: 通过案例学习多线程3种创建方式的差异 <br/>
* date: 2016年2月14日 下午11:11:06 <br/>
*
* @author Administrator
* @version
* @since JDK 1.6
*/
public class ThreadRunnable
{
/*
* 总票数
*/
public static int TOTAL_TICKETS = 10;
public static void main(String[] args)
{
/*
* extends实现方式无法模拟:多线程处理同一资源(即3个窗口买10张票)
*/
// ThreadExtends sellerExt = new ThreadExtends(TOTAL_TICKETS);
// Date begin = new Date();
// sellerExt.start();
// Date end = new Date();
// long millisTotal = end.getTime()-begin.getTime();
// System.out.println(TOTAL_TICKETS + " tikcets sold in " + millisTotal + " miliseconds.");
//下面的做法实际上实现的是3个窗口卖 30 张票
// ThreadExtends sellerExt1 = new ThreadExtends();
// ThreadExtends sellerExt2 = new ThreadExtends();
// ThreadExtends sellerExt3 = new ThreadExtends();
// sellerExt1.start();
// sellerExt2.start();
// sellerExt3.start();
/*
* implements实现方式则可以实现多窗口卖票(3个窗口买10张票)
*/
ThreadImplt seller = new ThreadImplt(TOTAL_TICKETS);
Thread window1 = new Thread(seller);
Thread window2 = new Thread(seller);
Thread window3 = new Thread(seller);
Date begin2 = new Date();
window1.start();
window2.start();
window3.start();
Date end2 = new Date();
long millisTotal2 = end2.getTime()-begin2.getTime();
System.out.println(TOTAL_TICKETS + " tikcets sold in " + millisTotal2 + " miliseconds.");
}
}
class ThreadExtends extends Thread
{
/*
* 总票数
*/
private int ticket;
/**
* Creates a new instance of ThreadExtends.
*
* @param ticket
*/
public ThreadExtends(int ticket)
{
this.ticket = ticket;
}
/**
*
* TODO 执行-买票.
* @see java.lang.Thread#run()
*/
public void run()
{
while (true)
{
if (ticket > 0)
{
System.out.println("[Window " + Thread.currentThread().getId() + "] is sailing tiket " + ticket--);
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{
//日志处理
throw new RuntimeException(e.toString()+"errorCode");
}
}
else
{
break;
}
}
}
}
class ThreadImplt implements Runnable
{
/*
* 总票数
*/
private int ticket;
/**
* Creates a new instance of ThreadImplt.
*
* @param ticket
*/
public ThreadImplt(int ticket)
{
this.ticket = ticket;
}
/**
* TODO 执行-买票.
* @see java.lang.Runnable#run()
*/
@Override
public void run()
{
while (true)
{
if (ticket > 0)
{
System.out.println("[Window " + Thread.currentThread().getId() + "] is sailing tiket " + ticket--);
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{
//日志处理
throw new RuntimeException(e.toString()+"errorCode");
}
}
else
{
break;
}
}
}
}
总结
java 共两种创建线程的方式:
一、无返回类,又分为两大类即 实现Runnable接口 与 继承 Thread 类(extends Thread 实际也属于实现Runnbale接口类 - Thread本身实现了Runnbale接口)。
- 我们很多情况下要把一个类的子类放到多线程中去,这个时候就就只能 通过implement创建: java单继承
- 相同程序代码的线程去处理同一个资源。比如说,铁路售票系统的模拟。
二、有返回类,即 实现Callable接口。
参考文献
1、三种实现线程的方式 http://www.cnblogs.com/yezhenhan/archive/2012/01/09/2317636.html 感谢博主!
2、 张孝祥-Java多线程与并发库高级应用 向张老师致敬!