Java util concurrent及基本线程原理简介
一:什么是JUC
JUC就是java.util.concurrent下面的类包,专门用于多线程的开发。
二:进程和线程的区别
进程是可并发执行的程序在某个数据集合上的一次计算活动,也是操作系统进行资源分配和调度的基本单位。
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
并发:多线程、多个线程操作一个资源类,快速交替过程。
并行:多核多CPU;
线程的状态:(java底层源码)
publicenumState{ NEW,//新建线程 RUNNABLE,//线程运行 BLOCKED,//线程阻塞 WAITING,//等待 TIMED_WAITING,//延时等待 TERMINATED;//线程销毁 }
三:wait和sleep的区别
1:类层面
wait------object
sleep-------Thread谁调用谁睡觉
2:是否释放锁层面
wait--------释放锁
sleep--------不释放锁
3:使用范围层面
wait,notify,notifyall只能在同步方法中或者同步代码块中使用
sleep可以再任意的地方使用
4:异常
sleep必须捕获异常
wait不需要捕获异常
四:线程的几种使用方式
1.优先级
publicfinalvoidsetPriority(intnewPriority)
更改线程的优先级。
默认为5,最小为1,最大为10
设置了优先级别之后,级别高并不是说你一定被优先调度,而是你的被优先调度的概率高而已。
publicclassTest{ publicstaticvoidmain(String[]args){ Tuzitz=newTuzi("兔子"); tz.setPriority(2); tz.start(); Wuguiwg=newWugui("乌龟"); wg.setPriority(8); wg.start(); } } publicclassWuguiextendsThread{ @Override publicvoidrun(){ for(inti=1;i<=100;i++){ System.out.println("我是乌龟我在跑。。"+"----"+this.getName()+"---"+this.getPriority()); } } publicWugui(Stringname){ super(name); } }
2.线程强制运行:join()
可以通过join()方法使得一个线程强制运行,线程强制运行期间,其他线程无法运行,必须等待此线程完成之后,才可以继续运行。
publicfinalvoidjoin()throwsInterruptedException
等待该线程终止。
publicfinalvoidjoin(longmillis)throwsInterruptedException
等待该线程终止的时间最长为millis毫秒。超时为0意味着要一直等下去。
packageThread1; classMyThreadimplementsRunnable{//实现Runnable接口 publicvoidrun(){//覆写run()方法 for(inti=0;i<50;i++){ System.out.println(Thread.currentThread().getName() +"运行,i="+i);//取得当前线程的名字 } } }; publicclassdemo1{ publicstaticvoidmain(Stringargs[]){ MyThreadmt=newMyThread();//实例化Runnable子类对象 Threadt=newThread(mt,"线程");//实例化Thread对象 t.start();//启动线程 for(inti=0;i<50;i++){ if(i>10){ try{ t.join();//线程强制运行 }catch(InterruptedExceptione){} } System.out.println("Main线程运行-->"+i); } } };
3线程的休眠(sleep)
在线程中允许一个线程进行暂时的休眠,直接使用Thread.sleep()方法即可。
sleep定义格式:
publicstaticvoidsleep(longmilis,intnanos)
throwsInterruptedException
首先,static,说明可以由Thread类名称调用,其次throws表示如果有异常要在调用此方法处处理异常。
所以sleep()方法要有InterruptedException异常处理,而且sleep()调用方法通常为Thread.sleep(500);形式。
控制当前线程休眠若干毫秒
*1秒=1000毫秒
*1秒=1000*1000*1000纳秒1000000000
packageThread1; classMyThreadimplementsRunnable{//实现Runnable接口 publicvoidrun(){//覆写run()方法 for(inti=0;i<50;i++){ try{ Thread.sleep(500);//线程休眠 }catch(InterruptedExceptione){} System.out.println(Thread.currentThread().getName() +"运行,i="+i);//取得当前线程的名字 } } }; publicclassdemo1{ publicstaticvoidmain(Stringargs[]){ MyThreadmt=newMyThread();//实例化Runnable子类对象 Threadt=newThread(mt,"线程");//实例化Thread对象 t.start();//启动线程 } };
4.线程的礼让(yield)
yield()方法实现线程的礼让。
packageThread1; classMyThreadimplementsRunnable{//实现Runnable接口 publicvoidrun(){//覆写run()方法 for(inti=0;i<5;i++){ try{ Thread.sleep(500);//休眠一下 }catch(Exceptione){} System.out.println(Thread.currentThread().getName() +"运行,i="+i);//取得当前线程的名字 if(i==2){ System.out.print("线程礼让:"); Thread.currentThread().yield();//首先获取当前线程,然后线程礼让 } } } }; publicclassdemo1{ publicstaticvoidmain(Stringargs[]){ MyThreadmy=newMyThread();//实例化MyThread对象 Threadt1=newThread(my,"线程A"); Threadt2=newThread(my,"线程B"); t1.start(); t2.start(); } };
5.判断线程是否在执行:isAlive
classMyThreadimplementsRunnable{//实现Runnable接口 publicvoidrun(){//覆写run()方法 for(inti=0;i<3;i++){ System.out.println(Thread.currentThread().getName() +"运行,i="+i);//取得当前线程的名字 } } }; publicclassThreadAliveDemo{ publicstaticvoidmain(Stringargs[]){ MyThreadmt=newMyThread();//实例化Runnable子类对象 Threadt=newThread(mt,"线程");//实例化Thread对象 System.out.println("线程开始执行之前-->"+t.isAlive());//判断是否启动 t.start();//启动线程 System.out.println("线程开始执行之后-->"+t.isAlive());//判断是否启动 for(inti=0;i<3;i++){ System.out.println("main运行-->"+i); } //以下的输出结果不确定 System.out.println("代码执行之后-->"+t.isAlive());//判断是否启动 } };
6.当前线程:CurrentThread()
程序可以通过currentThread()方法取得当前正在运行的线程对象,
classMyThreadimplementsRunnable{//实现Runnable接口 publicvoidrun(){//覆写run()方法 for(inti=0;i<3;i++){ System.out.println(Thread.currentThread().getName() +"运行,i="+i);//取得当前线程的名字 } } }; publicclassCurrentThreadDemo{ publicstaticvoidmain(Stringargs[]){ MyThreadmt=newMyThread();//实例化Runnable子类对象 newThread(mt,"线程").start();//启动线程 mt.run();//直接调用run()方法 } };
7.线程名称
1,在Thread类中可以通过getName()方法取得线程名称,通过setName()设置线程名称。
2,线程的名称一般在启动线程前设置,但也允许为运行的线程设置名称,允许两个Thread对象有相同名称,但是应该避免。
3,如果程序没有为线程指定名称,系统会自动为线程设置名称。
classMyThreadimplementsRunnable{//实现Runnable接口 publicvoidrun(){//覆写run()方法 for(inti=0;i<3;i++){ System.out.println(Thread.currentThread().getName() +"运行,i="+i);//取得当前线程的名字 } } }; publicclassThreadNameDemo{ publicstaticvoidmain(Stringargs[]){ MyThreadmt=newMyThread();//实例化Runnable子类对象 newThread(mt).start();//系统自动设置线程名称 newThread(mt,"线程-A").start();//手工设置线程名称 newThread(mt,"线程-B").start();//手工设置线程名称 newThread(mt).start();//系统自动设置线程名称 newThread(mt).start();//系统自动设置线程名称 } };
五:几种方法的比较
- Thread.sleep(longmillis),一定是当前线程调用此方法,当前线程进入阻塞,但不释放对象锁,millis后线程自动苏醒进入可运行状态。作用:给其它线程执行机会的最佳方式。
- Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的cpu时间片,由运行状态变会可运行状态,让OS再次选择线程。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。
- t.join()/t.join(longmillis),当前线程里调用其它线程1的join方法,当前线程阻塞,但不释放对象锁,直到线程1执行完毕或者millis时间到,当前线程进入可运行状态。
- obj.wait(),当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列。依靠notify()/notifyAll()唤醒或者wait(longtimeout)timeout时间到自动唤醒。
- obj.notify()唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。