——- android培训、java培训、期待与您交流! ———-
线程的运行状态
线程的运行状态在这里我们划分为五种状态。
依次为:被创建,运行,冻结,消亡,阻塞。
它们的关系见下图:
如上图所示:
- 线程在经初始化被创建后通过start方法被调用,进入了运行状态。
- 线程会因run方法运行结束或者强制终止而消亡。
- 线程会因为sleep进入冻结状态,当时间达到,又转入运行状态。
- 线程还会因为wait而进入冻结状态,因为notify方法而进入运行状态。
- 线程还会因为某些原因进入阻塞状态,再从阻塞状态转入运行状态。
需要注意的地方是:
- 运行是指具备运行资格,并具有执行权;
- 阻塞是指具备运行资格,但没有执行权;
- 冻结是指没有运行资格,但有执行权。
创建线程的第二种方式(Runnable)
下面通过售票的例子来推演创建线程的第二种方式。
需求:简单的卖票程序。多个窗口同时买票。
创建线程的第一种方式
步骤:
1、创建售票线程类,继承Thread
2、覆盖run方法(把需要让线程执行的代码写在run的方法体)
3、创建线程对象,调用start方法
代码1
//建立售票线程类
class TicketThread extends Thread
{
//私有化票额
private int ticket =30 ;
//覆盖run方法
public void run()
{
//建立一个循环售票,当票售完即停止
while(ticket > 0)
{
//打印当前线程对象售出的票号
System.out.println("Ticket "+ticket+" is saled by "+Thread.currentThread().getName());
//票号减一
ticket--;
}
}
}
class ThreadDemo3
{
public static void main(String[] args)
{
//建立4个售票线程
TicketThread t1 = new TicketThread();
TicketThread t2 = new TicketThread();
TicketThread t3 = new TicketThread();
TicketThread t4 = new TicketThread();
//调用start方法,启动4个线程,调用run方法
t1.start();
t2.start();
t3.start();
t4.start();
}
}
运行结果1
Ticket 30 is saled by Thread-1
Ticket 30 is saled by Thread-3
Ticket 30 is saled by Thread-0
Ticket 30 is saled by Thread-2
Ticket 29 is saled by Thread-0
Ticket 29 is saled by Thread-3
Ticket 29 is saled by Thread-1
Ticket 28 is saled by Thread-3
Ticket 28 is saled by Thread-0
Ticket 29 is saled by Thread-2
Ticket 27 is saled by Thread-0
Ticket 27 is saled by Thread-3
Ticket 28 is saled by Thread-1
Ticket 26 is saled by Thread-3
Ticket 26 is saled by Thread-0
Ticket 28 is saled by Thread-2
Ticket 25 is saled by Thread-0
Ticket 25 is saled by Thread-3
Ticket 27 is saled by Thread-1
Ticket 24 is saled by Thread-3
Ticket 24 is saled by Thread-0
Ticket 27 is saled by Thread-2
Ticket 23 is saled by Thread-0
Ticket 23 is saled by Thread-3
Ticket 26 is saled by Thread-1
Ticket 22 is saled by Thread-3
Ticket 22 is saled by Thread-0
Ticket 21 is saled by Thread-0
Ticket 26 is saled by Thread-2
Ticket 20 is saled by Thread-0
Ticket 21 is saled by Thread-3
Ticket 25 is saled by Thread-1
Ticket 20 is saled by Thread-3
Ticket 19 is saled by Thread-0
Ticket 25 is saled by Thread-2
Ticket 18 is saled by Thread-0
Ticket 19 is saled by Thread-3
Ticket 24 is saled by Thread-1
Ticket 18 is saled by Thread-3
Ticket 17 is saled by Thread-3
Ticket 16 is saled by Thread-3
Ticket 15 is saled by Thread-3
Ticket 14 is saled by Thread-3
Ticket 13 is saled by Thread-3
Ticket 12 is saled by Thread-3
Ticket 11 is saled by Thread-3
Ticket 10 is saled by Thread-3
Ticket 9 is saled by Thread-3
Ticket 8 is saled by Thread-3
Ticket 17 is saled by Thread-0
Ticket 24 is saled by Thread-2
Ticket 23 is saled by Thread-2
Ticket 22 is saled by Thread-2
Ticket 21 is saled by Thread-2
Ticket 20 is saled by Thread-2
Ticket 16 is saled by Thread-0
Ticket 15 is saled by Thread-0
Ticket 14 is saled by Thread-0
Ticket 7 is saled by Thread-3
Ticket 23 is saled by Thread-1
Ticket 22 is saled by Thread-1
Ticket 21 is saled by Thread-1
Ticket 6 is saled by Thread-3
Ticket 13 is saled by Thread-0
Ticket 19 is saled by Thread-2
Ticket 12 is saled by Thread-0
Ticket 11 is saled by Thread-0
Ticket 10 is saled by Thread-0
Ticket 9 is saled by Thread-0
Ticket 8 is saled by Thread-0
Ticket 7 is saled by Thread-0
Ticket 6 is saled by Thread-0
Ticket 5 is saled by Thread-0
Ticket 5 is saled by Thread-3
Ticket 4 is saled by Thread-3
Ticket 3 is saled by Thread-3
Ticket 2 is saled by Thread-3
Ticket 1 is saled by Thread-3
Ticket 20 is saled by Thread-1
Ticket 4 is saled by Thread-0
Ticket 3 is saled by Thread-0
Ticket 2 is saled by Thread-0
Ticket 18 is saled by Thread-2
Ticket 1 is saled by Thread-0
Ticket 19 is saled by Thread-1
Ticket 18 is saled by Thread-1
Ticket 17 is saled by Thread-1
Ticket 16 is saled by Thread-1
Ticket 15 is saled by Thread-1
Ticket 17 is saled by Thread-2
Ticket 16 is saled by Thread-2
Ticket 15 is saled by Thread-2
Ticket 14 is saled by Thread-1
Ticket 13 is saled by Thread-1
Ticket 12 is saled by Thread-1
Ticket 11 is saled by Thread-1
Ticket 10 is saled by Thread-1
Ticket 9 is saled by Thread-1
Ticket 8 is saled by Thread-1
Ticket 14 is saled by Thread-2
Ticket 13 is saled by Thread-2
Ticket 12 is saled by Thread-2
Ticket 11 is saled by Thread-2
Ticket 10 is saled by Thread-2
Ticket 9 is saled by Thread-2
Ticket 7 is saled by Thread-1
Ticket 8 is saled by Thread-2
Ticket 7 is saled by Thread-2
Ticket 6 is saled by Thread-1
Ticket 5 is saled by Thread-1
Ticket 4 is saled by Thread-1
Ticket 6 is saled by Thread-2
Ticket 3 is saled by Thread-1
Ticket 5 is saled by Thread-2
Ticket 2 is saled by Thread-1
Ticket 1 is saled by Thread-1
Ticket 4 is saled by Thread-2
Ticket 3 is saled by Thread-2
Ticket 2 is saled by Thread-2
结果显示:1张票被卖了4次。
改正方法:利用static 的共享特点
代码2
//改正后的代码
//建立售票线程类
class TicketThread extends Thread
{
//私有化票额,并利用static共享票号
private static int ticket =30 ;
//覆盖run方法
public void run()
{
//建立一个循环售票,当票售完即停止
while(ticket > 0)
{
//打印当前线程对象售出的票号
System.out.println("Ticket "+ticket+" is saled by "+Thread.currentThread().getName());
//票号减一
ticket--;
}
}
}
class ThreadDemo3
{
public static void main(String[] args)
{
//建立4个售票线程
TicketThread t1 = new TicketThread();
TicketThread t2 = new TicketThread();
TicketThread t3 = new TicketThread();
TicketThread t4 = new TicketThread();
//调用start方法,启动4个线程,调用run方法
t1.start();
t2.start();
t3.start();
t4.start();
}
}
运行结果2:
Ticket 30 is saled by Thread-1
Ticket 30 is saled by Thread-0
Ticket 30 is saled by Thread-3
Ticket 30 is saled by Thread-2
Ticket 27 is saled by Thread-3
Ticket 28 is saled by Thread-0
Ticket 24 is saled by Thread-0
Ticket 29 is saled by Thread-1
Ticket 23 is saled by Thread-0
Ticket 25 is saled by Thread-3
Ticket 20 is saled by Thread-3
Ticket 26 is saled by Thread-2
Ticket 19 is saled by Thread-3
Ticket 21 is saled by Thread-0
Ticket 22 is saled by Thread-1
Ticket 16 is saled by Thread-0
Ticket 17 is saled by Thread-3
Ticket 18 is saled by Thread-2
Ticket 13 is saled by Thread-3
Ticket 14 is saled by Thread-0
Ticket 15 is saled by Thread-1
Ticket 10 is saled by Thread-0
Ticket 11 is saled by Thread-3
Ticket 12 is saled by Thread-2
Ticket 7 is saled by Thread-3
Ticket 8 is saled by Thread-0
Ticket 9 is saled by Thread-1
Ticket 4 is saled by Thread-0
Ticket 5 is saled by Thread-3
Ticket 6 is saled by Thread-2
Ticket 1 is saled by Thread-3
Ticket 2 is saled by Thread-0
Ticket 3 is saled by Thread-1
结果仍然会有一张票被卖4次。
原因,由于是多线程运行,当t1调用run方法并执行到打印语句的时候,
其他线程抢占资源,ticket–;并没有执行。
改正方法:把ticket–;融合进打印语句。
小结:run方法里的语句不要太多。
代码3
//改正后的代码
//建立售票线程类
class TicketThread extends Thread
{
//私有化票额,并利用static共享票号
private static int ticket =30 ;
//覆盖run方法
public void run()
{
//建立一个循环售票,当票售完即停止
while(ticket > 0)
{
//打印当前线程对象售出的票号,并立即减少1张票额
System.out.println("Ticket "+(ticket--)+" is saled by "+Thread.currentThread().getName());
}
}
}
class ThreadDemo3
{
public static void main(String[] args)
{
//建立4个售票线程
TicketThread t1 = new TicketThread();
TicketThread t2 = new TicketThread();
TicketThread t3 = new TicketThread();
TicketThread t4 = new TicketThread();
//调用start方法,启动4个线程,调用run方法
t1.start();
t2.start();
t3.start();
t4.start();
}
}
运行结果3:
Ticket 29 is saled by Thread-2
Ticket 27 is saled by Thread-2
Ticket 26 is saled by Thread-2
Ticket 25 is saled by Thread-2
Ticket 30 is saled by Thread-1
Ticket 23 is saled by Thread-1
Ticket 22 is saled by Thread-1
Ticket 29 is saled by Thread-3
Ticket 28 is saled by Thread-0
Ticket 20 is saled by Thread-3
Ticket 18 is saled by Thread-3
Ticket 17 is saled by Thread-3
Ticket 21 is saled by Thread-1
Ticket 15 is saled by Thread-1
Ticket 14 is saled by Thread-1
Ticket 13 is saled by Thread-1
Ticket 12 is saled by Thread-1
Ticket 11 is saled by Thread-1
Ticket 24 is saled by Thread-2
Ticket 9 is saled by Thread-2
Ticket 8 is saled by Thread-2
Ticket 7 is saled by Thread-2
Ticket 10 is saled by Thread-1
Ticket 16 is saled by Thread-3
Ticket 19 is saled by Thread-0
Ticket 4 is saled by Thread-3
Ticket 2 is saled by Thread-3
Ticket 1 is saled by Thread-3
Ticket 5 is saled by Thread-1
Ticket 6 is saled by Thread-2
Ticket 3 is saled by Thread-0
现在结果正常了,但是有一个问题。
staitc在内存中呆的时间太长了,不利于资源的利用。
创建线程的第二种方式
通过查阅API发现:
创建线程的另一种方式是声明实现Runnable接口的类
步骤:
1、创建一个类并实现Runnable接口
2、覆盖Runnable中的run方法,把线程的代码存放在run的方法体
3、初始化该类。例如Ticket t =new Ticket();
4、创建线程,并把该类的对象传递给线程。例如:Thread t1 =Thread(t);
这是因为在Thread类中有这么一个构造函数Thread(Runnable target)
5、调用start方法,启动线程并调用run方法。
代码
//创建线程的另一种方式,声明实现Runnable接口的类Ticket
class Ticket implements Runnable
{
//私有化票额,因为接口是共享的,所以不需要static修饰,提高了效率
private int ticket =30 ;
//覆盖Runanble接口的run方法,把线程执行的代码存入
public void run()
{
//建立一个循环售票,当票售完即停止
while(ticket > 0)
{
//打印当前线程对象售出的票号,并立即减少1张票额
System.out.println("Ticket "+(ticket--)+" is saled by "+Thread.currentThread().getName());
}
}
}
class ThreadDemo3
{
public static void main(String[] args)
{
//创建一个Ticket对象,注意这里和第一种创建线程方法的不同。
//这里创建的是票的对象,第一种方法,创建的是售票线程的对象。
//在这里就共享了票额。
Ticket t =new Ticket();
//利用构造函数Thread(Runnable target)创建4个售票线程
//这里利用了多态的形式,建立了接口的引用
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
//调用start方法,启动线程并调用run方法,开始售票
t1.start();
t2.start();
t3.start();
t4.start();
}
}
运行结果:
Ticket 30 is saled by Thread-2
Ticket 27 is saled by Thread-3
Ticket 28 is saled by Thread-1
Ticket 29 is saled by Thread-0
Ticket 24 is saled by Thread-1
Ticket 25 is saled by Thread-3
Ticket 26 is saled by Thread-2
Ticket 20 is saled by Thread-2
Ticket 21 is saled by Thread-3
Ticket 22 is saled by Thread-1
Ticket 17 is saled by Thread-1
Ticket 16 is saled by Thread-1
Ticket 23 is saled by Thread-0
Ticket 15 is saled by Thread-1
Ticket 18 is saled by Thread-3
Ticket 12 is saled by Thread-3
Ticket 19 is saled by Thread-2
Ticket 11 is saled by Thread-3
Ticket 13 is saled by Thread-1
Ticket 14 is saled by Thread-0
Ticket 7 is saled by Thread-0
Ticket 8 is saled by Thread-1
Ticket 9 is saled by Thread-3
Ticket 10 is saled by Thread-2
Ticket 4 is saled by Thread-3
Ticket 5 is saled by Thread-1
Ticket 6 is saled by Thread-0
Ticket 1 is saled by Thread-1
Ticket 2 is saled by Thread-3
Ticket 3 is saled by Thread-2
结果显示:创建线程成功,票额售票成功!需求满足!
小结:
实现接口方式和继承方式有什么区别呢?
实现方式好处:避免了单继承的局限性。
在定义线程时,建议使用实现方式。
两种方式区别:
继承Thread:线程代码存放Thread子类run方法中。
实现Runnable,线程代码存在接口的子类的run方法。