第一种方式:继承Thread类(复写run方法)
class MyThread extends Thread{
public void run(){
for(int i=0;i<10;i++){
try {
sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(currentThread().getName()+":"+i);
}
}
}
public class ThreadDemo{
public static void main(String[] args){
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
mt1.run();
mt2.run();
}
}
执行结果
main:0
main:1
main:2
main:3
main:4
main:5
main:6
main:7
main:8
main:9
main:0
main:1
main:2
main:3
main:4
main:5
main:6
main:7
main:8
main:9
这样并没有并发执行,而是先执行完mt1线程,然后再执行mt2线程,并且执行在主线程中。
所以说如果想启动线程就必须使用Thread类中的start()方法,把上面的mt1.run()和mt2.run()改成.start()
执行结果
Thread-0:0
Thread-1:0
Thread-1:1
Thread-0:1
Thread-1:2
Thread-0:2
Thread-1:3
Thread-0:3
Thread-1:4
Thread-0:4
Thread-1:5
Thread-0:5
Thread-1:6
Thread-0:6
Thread-1:7
Thread-0:7
Thread-1:8
Thread-0:8
Thread-1:9
Thread-0:9
这时可以看到执行的才真正是两个MyTread,并且两个线程抢占CPU,谁抢到了谁就执行。
如果一个线程已经启动了,再次启动会抛出异常。即Thread存在单继承局限,所以我们有第二种实现方式
第二种方式:实现Runnable接口
class MyThread implements Runnable{
private String name;
public MyThread(String name){this.name = name;}
public void run(){
for(int i=0;i<10;i++){
System.out.println(name+":"+i);
}
}
}
public class ThreadDemo{
public static void main(String[] args){
MyThread mt1 = new MyThread("线程A");
MyThread mt2 = new MyThread("线程B");
Thread t1 = new Thread(mt1);
Thread t2 = new Thread(mt2);
t1.start();
t2.start();
}
}
既然有两种方式实现,那么我们到底实际中到底用哪种呢?其实Thread也是Runnable接口的子类
使用Thread类在操作多线程时无法达到资源共享,而实现Runnable接口则可以。
class MyThread extends Thread{
private int ticket = 5 ; // 表示一共有5张票
public void run(){ // 覆写run()方法
for(int i=0;i<100;i++){
if(this.ticket>0){
System.out.println("卖票:ticket = " + ticket--) ;
}
}
}
};
public class ThreadDemo04{
public static void main(String args[]){
MyThread mt1 = new MyThread() ; // 实例化对象
MyThread mt2 = new MyThread() ;
MyThread mt3 = new MyThread() ;
mt1start() ; // 调用线程主体
mt2.start() ;
mt3.start() ;
}
};
运行结果
卖票:ticket = 5
卖票:ticket = 4
卖票:ticket = 3
卖票:ticket = 2
卖票:ticket = 1
卖票:ticket = 5
卖票:ticket = 4
卖票:ticket = 3
卖票:ticket = 2
卖票:ticket = 1
卖票:ticket = 5
卖票:ticket = 4
卖票:ticket = 3
卖票:ticket = 2
卖票:ticket = 1
发现各自买了五张票,资源没有共享,但是如果用Runnable接口实现
class MyThread implements Runnable{
private int ticket = 5 ; // 表示一共有5张票
public void run(){ // 覆写run()方法
for(int i=0;i<100;i++){
if(this.ticket>0){
System.out.println("卖票:ticket = " + ticket--) ;
}
}
}
};
public class Test1{
public static void main(String args[]){
MyThread mt1 = new MyThread() ; // 实例化对象
//有效避免单继承问题,适合多个相同程序代码的线程去处理同一资源
new Thread(mt1).start();
new Thread(mt1).start();
new Thread(mt1).start();
}
};
运行结果为
卖票:ticket = 5
卖票:ticket = 4
卖票:ticket = 3
卖票:ticket = 2
卖票:ticket = 1
发现资源共享了,所以开发中使用Runnable接口 是合适的