java多线程实现有两种方式及其实现售票系统的实例
1、继承Thread类 ,覆盖run() 这个方式有个限制,就是只能继承一个类,对于还需要继承别的类的类就不适合使用了
资源不同共享
2、实现Runnable接口 ,覆盖run()由于Runnable没有start()方法启动方式,只能通过把实例放到Thread对象的然后通过start()启动线程
优势:1)避免单继承的局限,一个类可以实现多个接口
2)适合于资源的共享
以下是两个不同方式实现多线程的例子:
继承Thread方式,代码如下
package com.sunrise.thread;
/**
* 线程类 继承Thread (弊端:一个类只能继承一个父类,开发中这种方式用的比较少)
* 1、使用run()方法启动多线程 线程不会交互执行,而是等一个执行完之后在执行第二个线程
* 这就失去了多线程的意义
* 2、使用start() 启动多线程,会交互执行(通过JVM去找到run方法的)
*/
public class MyThread extends Thread{
private String name;
public MyThread(String name) {
super();
this.name = name;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=10;i>0;i--){
System.out.println(Thread.currentThread()+":"+name);
}
}
}
package com.sunrise.thread;
public class ThreadMain {
public static void main(String[] args) {
//new MyThread("first").run();//这种启动不能对象交互执行
//new MyThread("second").run();
new MyThread("first").start();//这种启动可以对象交互执行
new MyThread("second").start();
}
}2、Runnbale实现代码如下:
package com.sunrise.thread;
/**
* 这种方式实现多线程,是开发中的正统操作
* 1、由于Runnable没有start方式,只能通过Thread的start()启动线程
*/
public class MyRunnableThread implements Runnable{
private String name;
public MyRunnableThread(String name) {
super();
this.name = name;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread()+":"+name);
}
}
}
package com.sunrise.thread;
public class RunableThreadMain {
public static void main(String[] args) {
//由于Runnable没有start方式,只能把它放到Thread对象中然后通过start()启动线程
new Thread(new MyRunnableThread("first")).start();
new Thread(new MyRunnableThread("second")).start();
}
}
针对资源共享问题,我也用两个方式都写了一个售票系统的demo,有啥不对的地方还请大虾多多指导,下面是代码:
package com.sunrise.thread.tk;
/**
* 卖票多线程Runnable实现
*/
public class TecketRunableThread implements Runnable{
private int ticket = 500000;//总票数
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
//若有票,则卖出 票数-1
if(this.ticket>0)
System.out.println(Thread.currentThread()+":"+this.ticket--);
else
break;//跳出方法来结束线程
}
}
}
package com.sunrise.thread.tk;
/**
* 不同共享资源,
* 这里就通过使用其他类(SellTask)的资源来达到同样的目的
*/
public class TecketThread extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
//System.out.println(Thread.currentThread()+":"+SellTask.ticket);
while(true){
SellTask.excute();
if(SellTask.ticket==0) break;//跳出方法来结束线程
}
}
}
package com.sunrise.thread.tk;
/**
* 这里的资源由于多线程使用到
* 所以要做好方法同步和代码快点的同步问题synchronized
*/
public class SellTask {
public static int ticket=500000;
/**
* 执行买票任务
* 指定同步,只能一个线程在同一个时间使用这个方法
*/
public synchronized static void excute(){
synchronized (SellTask.class) {
if(ticket>0)
System.out.println(Thread.currentThread()+":"+ticket--);
}
}
}
package com.sunrise.thread.tk;
public class TeckectMain {
public static void main(String[] args) {
//SellByRunnable();
SellByThread();
}
/**
*Runnable 资源共享的卖票方式
* 只是用一个Runnable线程来达到资源共享的目的
*/
public static void SellByRunnable(){
//下面的线程共享 trt的资源
TecketRunableThread trt = new TecketRunableThread();
for(int i=0;i<100;i++){
new Thread(trt).start();//卖票线程
}
//new Thread(trt).start();//卖票线程
}
/**
* Thread 资源共享的卖票方式
* 通过SellTask卖票任务类的
* 同步来限制使用资源而达到资源共享的目的
*/
public static void SellByThread(){
//循环产生2个Thread线程
for(int i=0;i<2;i++){
TecketThread trt = new TecketThread();
trt.start();
}
}
}