Java线程(转)

1、Java线程的实现。

 第一种方式可以通过继承Thread。在Thread类中,有许多关于线程操作的方法,比如:sleep();activeCount();等

 继承Thread的代码:

复制代码
public class MyThread extends Thread{
    
    public static void main(String[] args) {
        MyThread myth = new MyThread();
     MyThread myth1 = new MyThread(); myth.start();//启动一个线程
     myth1.start(); } @Override
public void run() { System.out.println(Thread.currentThread().getName());//得到当前线程名 } }
复制代码

  第二种方式通过实现Runnable。通过重写run()方法,实现自己的业务逻辑。jvm会自动调用run()方法。

 实现Runnale的代码:

复制代码
public class RunThread implements Runnable {

        public void run() {
          System.out.print(Thread.currentThread().getName());
    }
        
        public static void main(String[] args){
        RunThread rtA = new RunThread();
        
        new Thread(rtA).start();
        new Thread(rtA).start();
        new Thread(rtA).start();
        System.out.println(Thread.activeCount());//当前活跃线程数
    }
}
复制代码

二者的区别:

 我们可以从Thread源码得知,Thread实际上也是实现了Runnable接口。

  1、如果继承了Thread,那么就不能在去继承其他的类了,而实现Runnable接口就不会有这样的问题,提高类的可扩展性。

  2、从上面的代码看,第一种方式开启多个线程话,就必须创建多个对象;第二种方式开启多个线程,就可以只使用一个对象,这样就可以是实现资源的共享。

 以买票为列:

复制代码
package org.demo.dff;  
class MyThread extends Thread{  
private int ticket=10;  
public void run(){  
for(int i=0;i<20;i++){  
if(this.ticket>0){  
System.out.println("卖票:ticket"+this.ticket--);  
}  
}  
}  
};
复制代码

下面通过三个线程对象,同时卖票:

复制代码
package org.demo.dff;  
public class ThreadTicket {  
public static void main(String[] args) {  
MyThread mt1=new MyThread();  
MyThread mt2=new MyThread();  
MyThread mt3=new MyThread();  
mt1.start();//每个线程都各卖了10张,共卖了30张票  
mt2.start();//但实际只有10张票,每个线程都卖自己的票  
mt3.start();//没有达到资源共享  
}  
} 
复制代码

如果用Runnable就可以实现资源共享,下面看例子:

复制代码
package org.demo.runnable;  
class MyThread implements Runnable{  
private int ticket=10;  
public void run(){  
for(int i=0;i<20;i++){  
if(this.ticket>0){  
System.out.println("卖票:ticket"+this.ticket--);  
}  
}  
}  
}  
package org.demo.runnable;  
public class RunnableTicket {  
public static void main(String[] args) {  
MyThread mt=new MyThread();  
new Thread(mt).start();//同一个mt,但是在Thread中就不可以,如果用同一  
new Thread(mt).start();//个实例化对象mt,就会出现异常  
new Thread(mt).start();  
}  
}; 
复制代码

2、线程的状态(state)

  新生状态(New):当一个线程的实例被创建时,即new的时候,此时线程处于一个新生状态,新生状态的线程有自己的内存空间,但是线程没有运行(调用start()运行),此时线程不是活的。(not alive)

  就绪状态(Runnable): 通过调用线程实例的start()方法来启动线程使线程进入就绪状态(runnable);处于就绪状态的线程已经具备了运行条件,但还没有被分配到CPU即不一定会被立即执行,此时处于线程就绪队列,等待系统为其分配CPCU,等待状态并不是执行状态; 此时线程是活着的(alive);

  运行状态(Running): 一旦获取CPU(被JVM选中),线程就进入运行(running)状态,线程的run()方法才开始被执行;在运行状态的线程执行自己的run()方法中的操作,直到调用其他的方法而终止、或者等待某种资源而阻塞、或者完成任务而死亡;如果在给定的时间片内没有执行结束,就会被系统给换下来回到线程的等待状态;此时线程是活着的(alive);

  阻塞状态(Blocked):通过调用join()、sleep()、wait()或者资源被暂用使线程处于阻塞(blocked)状态;处于Blocking状态的线程仍然是活着的(alive)

  死亡状态(Dead):当一个线程的run()方法运行完毕或被中断或被异常退出,该线程到达死亡(dead)状态。此时可能仍然存在一个该Thread的实例对象,当该Thready已经不可能在被作为一个可被独立执行的线程对待了,线程的独立的call stack已经被dissolved。一旦某一线程进入Dead状态,他就再也不能进入一个独立线程的生命周期了。对于一个处于Dead状态的线程调用start()方法,会出现一个运行期(runtime exception)的异常;处于Dead状态的线程不是活着的(not alive)

原文地址:https://www.cnblogs.com/liutoutou/p/3584024.html