java多线程:创建、join方法

来源:互联网 发布:买家怎么取消农村淘宝 编辑:程序博客网 时间:2024/06/03 19:32

一、进程和线程的区别
进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1–n个线程。
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。
线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。
新建状态(New):新建的线程处于新建状态,如:Thread t = new MyThread();
就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;
运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就 绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;
阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:
1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;
2.同步阻塞 – 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
3.其他阻塞 – 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
二、实现线程的方式:
JAVA多线程实现方式主要下面几种:继承Thread类、实现Runnable接口、实现Callable接口、使用ExecutorService。
三、线程调度
Java线程优先级高的线程会获得较多的运行机会
Java线程的优先级用整数表示,取值范围是1~10,Thread类有以下三个静态常量:
static int MAX_PRIORITY:线程可以具有的最高优先级,取值为10。
static int MIN_PRIORITY:线程可以具有的最低优先级,取值为1。
static int NORM_PRIORITY:分配给线程的默认优先级,取值为5。
每个线程都有默认的优先级,缺省优先级为 NORM_PRIORITY。
有关优先级的方法有两个:
final void setPriority(int newp) : 修改线程的当前优先级
final int getPriority() : 返回线程的优先级
主线程的默认优先级为Thread.NORM_PRIORITY。
线程的优先级有继承关系,比如A线程中创建了B线程,那么B将和A具有相同的优先级。
JVM提供了10个线程优先级,但与常见的操作系统都不能很好的映射。如果希望程序能移植到各个操作系统中,
应该仅仅使用Thread类有以下三个静态常量作为优先级,这样能保证同样的优先级采用了同样的调度方式。

//main方法也是一个线程   是普通优先级public class Test {    public static void main(String[] args) throws InterruptedException {        ThreadTest t1=new ThreadTest();        t1.setName("线程1");//设置线程的名称        t1.start();//启动线程  不能直接调用run方法//      t1.sleep(3000);             ThreadTest t2=new ThreadTest();        t2.setName("线程2");        t2.start();//      t2.start();//不能两次调用start方法//      t2.setPriority(10);//设置线程对象的优先级   参数的范围是0-10 默认为5   数值越大表示执行的时间越长的概率越高//      t1.setPriority(1);//      t1.setPriority(Thread.NORM_PRIORITY);//也可以使字段常量  MAX_PRIORITY  MIN_PRIORITY  NORM_PRIORITY        /*Thread t = Thread.currentThread();//获得当前正在执行的线程对象        for(int i=0;i<600;i++){            System.out.println(t.getName()+"  "+i);        }*/    }}//线程:继承Thread类  重写run方法class ThreadTest extends Thread{    @Override    public void run() {        for(int i=0;i<5000;i++){            /*if(i==100){                try {                    sleep(2000);//让线程对象休眠    参数是毫秒数                } catch (InterruptedException e) {                    e.printStackTrace();                }            }*/            yield();//谦让   暂停当前正在执行的线程对象,并执行其他线程            System.out.println(this.getName()+"  "+i);//获得线程的名称        }    }   }

四、线程join方法
join()方法,等待其他线程终止。在当前线程中调用另一个线程的join()方法,则当前线程转入阻塞状态,直到另一个进程运行结束,当前线程再由阻塞转为就绪状态。

//线程对象互相join 也会死锁public class Test1 {    public static void main(String[] args) {        Thread1 t1=new Thread1();        Thread2 t2=new Thread2();        t1.t2=t2;//给线程对象的属性赋值        t1.setName("线程1");        t2.t1=t1;        t2.setName("线程2");        t1.start();        t2.start();    }}class Thread1 extends Thread{    Thread2 t2;    @Override    public void run() {        for(int i=0;i<500;i++){            if(i==400){                try {                    t2.join();                } catch (InterruptedException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }                       System.out.println(getName()+"  "+i);        }    }}class Thread2 extends Thread{    Thread1 t1;    @Override    public void run() {        for(int i=0;i<500;i++){            if(i==100){                try {                    t1.join();//让出当前线程 让t1线程对象执行完                } catch (InterruptedException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }            System.out.println(getName()+"  "+i);        }    }}

参考资料:

Java总结篇系列:Java多线程(一)

0 0
原创粉丝点击