多线程的实现
可以通过继承Tread类和实现Runnable接口来实现多线程,通过卖票实现多线程代码如下:
package Thread;
// 继承Thread类
class ConductorThread extends Thread{
private int ticketNum = 5;
@Override
public void run() {
for(int i=5;i>0;i--) {
if(this.ticketNum>0) {
this.ticketNum--;
System.out.println(Thread.currentThread().getName() + "卖了1张票剩余" + this.ticketNum+ "张票");
}
}
}
}
//实现Runnable接口
class ConductorRunnable implements Runnable{
private int ticketNum = 5;
@Override
public void run() {
for(int i=5;i>0;i--) {
if(this.ticketNum>0) {
this.ticketNum--;
System.out.println(Thread.currentThread().getName()+"卖了1张票剩余"+this.ticketNum+"张票");
}
}
}
}
public class RailwayStation {
public static void main(String args[]) {
// 创建实例对象
ConductorThread conductorThread = new ConductorThread();
ConductorRunnable conductorRunnable = new ConductorRunnable();
//为实例对象创建连个售票员线程
Thread conductor1 = new Thread(conductorThread,"售票员1") ;
Thread conductor2 = new Thread(conductorThread,"售票员2") ;
Thread conductor3 = new Thread(conductorRunnable,"售票员3");
Thread conductor4 = new Thread(conductorRunnable,"售票员4");
// 启动线程
conductor1.start();
conductor2.start();
conductor3.start();
conductor4.start();
}
}
运行结构:
售票员1卖了1张票剩余4张票
售票员1卖了1张票剩余2张票
售票员1卖了1张票剩余1张票
售票员1卖了1张票剩余0张票
售票员2卖了1张票剩余3张票
售票员4卖了1张票剩余3张票
售票员3卖了1张票剩余3张票
售票员4卖了1张票剩余2张票
售票员3卖了1张票剩余1张票
售票员4卖了1张票剩余0张票
如果创建了两个实例对象,则会卖两倍的票数,这是因为普通成员变量的ticketNum会被初始化两次。
Thread和Runnable的区别
阅读源码
public interface Runnable {
/**
* When an object implementing interface Runnable
is used
* to create a thread, starting the thread causes the object's
* run
method to be called in that separately executing
* thread.
*
* The general contract of the method run
is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
public
class Thread implements Runnable {
/* Make sure registerNatives is the first thing does. */
private static native void registerNatives();
static {
registerNatives();
}
private volatile String name;
private int priority;
private Thread threadQ;
private long eetop;
/* Whether or not to single_step this thread. */
private boolean single_step;
......
}
Thread类实现了Runnable接口,当一个类A继承了类B,类B没有继承Thread,由于java的单继承性,类B要想实现多线程,则不能继承Thread类,只能实现Runnable接口。
Runnable可以看做一个一个具体的task,在task下有多个线程共同来执行这个task,不同线程之间的资源是可以共享的。Thread作为线程的载体,不同Thread对象之间不可以进行资源共享。
线程的状态
新建状态
new出新对象,调用start方法,线程进入就绪状态,已经启动的线程不能再次调用start方法
就绪状态
具备的运行条件,但是没有分到CPU,等待系统为其分配CPU
运行状态
运行状态的线程有可能变为阻塞状态
注: 当发生如下情况是,线程会从运行状态变为阻塞状态:
①线程调用sleep方法主动放弃所占用的系统资源
②线程调用一个阻塞式IO方法,在该方法返回之前,该线程被阻塞
③线程试图获得一个同步监视器,但更改同步监视器正被其他线程所持有
④线程在等待某个通知(notify)
⑤程序调用了线程的suspend方法将线程挂起。不过该方法容易导致死锁,所以程序应该尽量避免使用该方法。
阻塞状态
线程执行了sleep方法或者等待I/O设备
死亡状态
线程执行完毕或者强制终止