第一种方式:通过继承Thread类创建
new Thread() {// new Threah(){}表示创建一个匿名子类的实例对象,{}内是子类的代码
// 重写父类的run方法
public void run() {
while (true) {
try {// 必需try...catch
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
}.start();
第二种方式:通过实现Runnable接口创建
// new Thread(new Runnable(){}).start();表示调用Threah对象接受的Runnable对象的run方法.
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
}).start();
Thread内部run方法的代码:
public void run() {
if (target != null) {
target.run();
}
}
target 是Runnable子类的实例对象,若通过Thread子类实现,则优先调用子类的run方法.其实Thread类也是实现了 Runnable接口.
使用第二种方式创建的好处:
1、 多个线程共享同一份资源
2、可以避免由于java单继承特性带来的局限性。
无论是继承还是实现都需要重写run方法,此方法为线程的主体.
模拟多个线程共享同一份资源
问题:一个火车站当天去往某地的车票一共有50张,由多个售票点负责售票.
若通过继承方式如下:
class Demo extends Thread
{
private int ticket = 50 ;
public void run()
{
while(this.ticket>0)
{
System.out.println("卖票:"+this.ticket--) ;
}
}
};
public class ThreadDemo04
{
public static void main(String args[])
{
// 准备四个售票点
Demo d1 = new Demo() ;
Demo d2 = new Demo() ;
Demo d3 = new Demo() ;
Demo d4 = new Demo() ;
d1.start() ;
d2.start() ;
d3.start() ;
d4.start() ;
}
};
但这样打印的结果是:每个售票点都售票50张,不符合实际要求!当然你可以把ticket设置成为static,这样也可以符合要求.
第二种方式:
class Demo05 implements Runnable
{
private int ticket = 50 ;
public void run()
{
while(this.ticket>0)
{
System.out.println("卖票:"+this.ticket--) ;
}
}
};
public class ThreadDemo05
{
public static void main(String args[])
{
// 四个售票点应该控制同一个资源:50
Demo05 d = new Demo05() ;
Thread t1 = new Thread(d) ;
Thread t2 = new Thread(d) ;
Thread t3 = new Thread(d) ;
Thread t4 = new Thread(d) ;
t1.start() ;
t2.start() ;
t3.start() ;
t4.start() ;
}
};
由于不同的线程调用的是同一个对象(Demo05 d = new Demo05() )的run方法,因此访问的ticket 都是同一个对象的成员属性.
但这两份代码都存在线程安全问题:ticket到最后可能会变成一个负数,如在while循环开始加一段:
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
这样ticket最后打印的值就会出现负数! 解决的方法线程同步.在下一节里讲