Java5线程.docx
- 文档编号:23404765
- 上传时间:2023-05-16
- 格式:DOCX
- 页数:21
- 大小:78.24KB
Java5线程.docx
《Java5线程.docx》由会员分享,可在线阅读,更多相关《Java5线程.docx(21页珍藏版)》请在冰豆网上搜索。
Java5线程
Java-5线程
1.线程的基本概念
Ø线程是一个程序里面不同的执行路径。
Ømain方法是主线程。
Ø进程:
是一个静态的概念。
机器上的一个class文件、一个exe文件都是进程。
进程的执行:
进程里的main方法开始运行,进程变为线程。
进程是一个静态概念,在我们机器里运行的都是线程。
Ø我们的操作系统都是支持多进程、多线程的。
只有DOS是支持单线程、单进程的。
ØCPU速度快,分为很多时间块,在一个时间块执行一个线程,在另一个时间块执行另一个线程。
也就是说,一会执行这个线程,一会执行另一个线程。
由于CPU的速度快,给人的感觉是多线程。
其实,在一个时间点上,CPU只有一个线程在运行。
真正的多线程CPU像现在的双核。
2.Java线程
Java的线程是通过java.lang.Thread类来实现的。
java虚拟机(JVM)启动时会有一个由主方法(publicstaticvoidmain(){})所定义的线程;我们可以通过创建Thread的实例来创建新的线程;每个线程都是通过特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体;通过调用Thread类的strat()方法来启动一个线程。
3.线程的创建和启动
有两种方式创建新的线程
3.1定义线程类实现Runnable接口
例如:
publicclassTest{
publicstaticvoidmain(String[]args){
RunnableTestrunnableTest=newRunnableTest();
Threadthread=newThread(runnableTest);
//线程启动,必须调用start()方法
thread.start();
for(inti=0;i<20;i++){
System.out.println("主线程------"+i);
}
}
}
classRunnableTestimplementsRunnable{
publicvoidrun(){
for(inti=0;i<20;i++){
System.out.println("新的线程:
"+i);
}
}
}
运行结果:
新的线程:
0
新的线程:
1
新的线程:
2
新的线程:
3
新的线程:
4
新的线程:
5
新的线程:
6
新的线程:
7
新的线程:
8
新的线程:
9
新的线程:
10
新的线程:
11
新的线程:
12
新的线程:
13
新的线程:
14
新的线程:
15
新的线程:
16
新的线程:
17
主线程------0
主线程------1
主线程------2
主线程------3
主线程------4
主线程------5
主线程------6
主线程------7
主线程------8
主线程------9
主线程------10
主线程------11
主线程------12
主线程------13
主线程------14
主线程------15
主线程------16
主线程------17
主线程------18
新的线程:
18
主线程------19
新的线程:
19
可以看出:
主线程和新线程是交替都在运行的。
程序里有了不同的执行路径。
如果代码变成如下所示:
publicclassTest{
publicstaticvoidmain(String[]args){
RunnableTestrunnableTest=newRunnableTest();
//没有实现Thread的话,只是方法调用
runnableTest.run();
//Threadthread=newThread(runnableTest);
//thread.start();
for(inti=0;i<20;i++){
System.out.println("主线程------"+i);
}
}
}
classRunnableTestimplementsRunnable{
publicvoidrun(){
for(inti=0;i<20;i++){
System.out.println("新的线程:
"+i);
}
}
}
运行结果:
新的线程:
0
新的线程:
1
新的线程:
2
新的线程:
3
新的线程:
4
新的线程:
5
新的线程:
6
新的线程:
7
新的线程:
8
新的线程:
9
新的线程:
10
新的线程:
11
新的线程:
12
新的线程:
13
新的线程:
14
新的线程:
15
新的线程:
16
新的线程:
17
新的线程:
18
新的线程:
19
主线程------0
主线程------1
主线程------2
主线程------3
主线程------4
主线程------5
主线程------6
主线程------7
主线程------8
主线程------9
主线程------10
主线程------11
主线程------12
主线程------13
主线程------14
主线程------15
主线程------16
主线程------17
主线程------18
主线程------19
可以看出:
先运行完方法调用,再运行for循环,还是一条执行路径,没有新的执行路径。
3.2定义一个Thread的子类并重写其run方法
例如:
publicclassTest{
publicstaticvoidmain(String[]args){
ThreadTestthreadTest=newThreadTest();
//线程启动,必须调用start()方法
threadTest.start();
for(inti=0;i<20;i++){
System.out.println("主线程------"+i);
}
}
}
classThreadTestextendsThread{
publicvoidrun(){
for(inti=0;i<20;i++){
System.out.println("新的线程:
"+i);
}
}
}
运行结果:
主线程------0
主线程------1
主线程------2
主线程------3
主线程------4
主线程------5
主线程------6
主线程------7
主线程------8
主线程------9
主线程------10
主线程------11
主线程------12
主线程------13
主线程------14
主线程------15
主线程------16
新的线程:
0
主线程------17
新的线程:
1
主线程------18
新的线程:
2
主线程------19
新的线程:
3
新的线程:
4
新的线程:
5
新的线程:
6
新的线程:
7
新的线程:
8
新的线程:
9
新的线程:
10
新的线程:
11
新的线程:
12
新的线程:
13
新的线程:
14
新的线程:
15
新的线程:
16
新的线程:
17
新的线程:
18
新的线程:
19
可以看出:
主线程和新线程是交替都在运行的。
程序里有了不同的执行路径。
4.线程状态转换
4.1线程控制基本方法
方法
功能
isAlive()
判断线程是否还“活”着,即线程是否还未终止
getPriority()
获得线程的优先级数值
setPriority()
设置线程的优先级数值
Thread.sleep()
将当前线程睡眠指定毫秒数
join()
调用某线程的该方法,将当前线程与该线程“合并”,即等待该线程结束,再恢复当前线程的运行
yield()
让出CPU,当前线程进入就绪队列等待调度
wait()
当前线程进入对象的waitpool
notify()/notifyAll()
唤醒对象的waitpool中的一个/所有等待线程
4.1.1sleep方法
Ø可以调用Thread的静态方法:
publicvoidstaticsleep(longmillis)throwsInterruptedException
使得当前线程休眠(暂时停止执行millis毫秒)
Ø由于是静态方法,sleep可以由类名直接调用:
Thread.sleep(…)
示例:
importjava.util.Date;
/**
*这个小例子演示的是停止子线程的方法
*下面这个例子中,每1秒打印一次时间
*当第10秒时,停止
*需要注意的是:
该方法并不是停止线程最好的方法
*/
publicclassTestInterrupt{
publicstaticvoidmain(String[]args){
TestThreadtestThread=newTestThread();
testThread.start();
try{
Thread.sleep(10000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
//停止线程的方法
testThread.interrupt();
}
}
classTestThreadextendsThread{
publicvoidrun(){
while(true){
System.out.println("===="+newDate()+"====");
try{
sleep(1000);
}catch(InterruptedExceptione){
return;
}
}
}
}
示例:
importjava.util.Date;
/**
*上面的方法不是停止线程最好的办法
*那么,最好的办法是什么呢?
*如下方法
*/
publicclassTestInterrupt{
publicstaticvoidmain(String[]args){
TestThreadtestThread=newTestThread();
testThread.start();
try{
Thread.sleep(10000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
//停止线程
testThread.flag=false;
}
}
classTestThreadextendsThread{
booleanflag=true;
publicvoidrun(){
while(flag){
System.out.println("===="+newDate()+"====");
try{
sleep(1000);
}catch(InterruptedExceptione){
return;
}
}
}
}
4.1.2join方法
Ø合并某个线程
示例:
publicclassTestJoin{
publicstaticvoidmain(String[]args){
Testthreadtestthread=newTestthread();
testthread.start();
try{
//将线程testthread与主线程合并
//相当于方法调用
testthread.join();
}catch(InterruptedExceptione){
e.printStackTrace();
}
for(inti=0;i<=10;i++){
System.out.println("iammainthread");
}
}
}
classTestthreadextendsThread{
publicvoidrun(){
for(inti=0;i<=10;i++){
System.out.println("iam"+getName());
try{
sleep(1000);
}catch(InterruptedExceptione){
return;
}
}
}
}
4.1.3yield方法
Ø让出CPU,给其它线程执行的机会
示例:
publicclassTestJoin{
publicstaticvoidmain(String[]args){
Testthreadt1=newTestthread("t1");
Testthreadt2=newTestthread("t2");
t1.start();
t2.start();
}
}
classTestthreadextendsThread{
//使用这个构造方法可以让一个类new出N个线程
Testthread(Strings){
super(s);
}
publicvoidrun(){
for(inti=1;i<=100;i++){
System.out.println("iam"+getName()+""+i);
if(i%10==0){
yield();
}
}
}
}
4.1.4线程的优先级别
ØJava提供了一个线程调度器来监控程序中启动后进入就绪状态的所有线程。
线程调度器按照线程的优先级决定应调度哪个线程来执行
Ø线程的优先级用数字表示,范围从1到10,一个线程的缺省优先级是5
Thread.MIN_PRIORITY=1
Thread.MAX_PRIORITY=10
Thread.NORM_PRIORITY=5
示例:
publicclassTestJoin{
publicstaticvoidmain(String[]args){
Threadt1=newThread(newT1());
Threadt2=newThread(newT2());
t1.setPriority(Thread.NORM_PRIORITY+3);
t1.start();
t2.start();
}
}
classT1implementsRunnable{
publicvoidrun(){
for(inti=0;i<100;i++){
System.out.println("T1:
"+i);
}
}
}
classT2implementsRunnable{
publicvoidrun(){
for(inti=0;i<100;i++){
System.out.println("T2---"+i);
}
}
}
5.线程同步
先看下面一个示例:
publicclassTestSyncimplementsRunnable{
Timertimer=newTimer();
publicstaticvoidmain(String[]args){
TestSynctestSync=newTestSync();
Threadt1=newThread(testSync);
Threadt2=newThread(testSync);
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
publicvoidrun(){
timer.add(Thread.currentThread().getName());
}
}
classTimer{
privatestaticintnum=0;
publicvoidadd(Stringname){
num++;
try{
Thread.sleep
(1);
}catch(InterruptedExceptione){
e.printStackTrace();
}
System.out.println(name+",你是第"+num+"个使用timer的线程");
}
}
在这个示例中,我们希望看到的运行结果是:
t1,你是第1个使用timer的线程
t2,你是第2个使用timer的线程
但是,真实的运行结果是:
t1,你是第2个使用timer的线程
t2,你是第2个使用timer的线程
为什么会这样呢?
我们来分析这个程序:
先是t1执行add方法,num变为1,紧接着t1休眠;t2执行add方法,num变为2,紧接着t2休眠;t1从休眠状态苏醒,接着执行。
因此,打印结果会如上所示,都是“第2个使用。
。
”。
怎么解决这个问题呢?
用synchronized
synchronized关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者CD等),有的话要等正在使用这个方法的线程B(或者CD)运行完这个方法后再运行此线程A,没有的话,直接运行它包括两种用法:
synchronized方法和synchronized块。
5.1synchronized方法
用synchronized方法修改示例代码如下:
publicclassTestSyncimplementsRunnable{
Timertimer=newTimer();
publicstaticvoidmain(String[]args){
TestSynctestSync=newTestSync();
Threadt1=newThread(testSync);
Threadt2=newThread(testSync);
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
publicvoidrun(){
timer.add(Thread.currentThread().getName());
}
}
classTimer{
privatestaticintnum=0;
//使用synchronized方法
publicsynchronizedvoidadd(Stringname){
num++;
try{
Thread.sleep
(1);
}catch(InterruptedExceptione){
e.printStackTrace();
}
System.out.println(name+",你是第"+num+"个使用timer的线程");
}
}
运行结果:
t1,你是第1个使用timer的线程
t2,你是第2个使用timer的线程
5.2synchronized块
用synchronized块修改示例代码如下:
publicclassTestSyncimplementsRunnable{
Timertimer=newTimer();
publicstaticvoidmain(String[]args){
TestSynctestSync=newTestSync();
Threadt1=newThread(testSync);
Threadt2=newThread(testSync);
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
publicvoidrun(){
timer.add(Thread.currentThread().getName());
}
}
classTimer{
privatestaticintnum=0;
publicvoidadd(Stringname){
//使用synchronized块
synchronized(this){
num++;
try{
Thread.sleep
(1);
}catch(InterruptedExceptione){
e.printStackTrace();
}
System.out.println(name+",你是第"+num+"个使用timer的线程");
}
}
}
运行结果:
t1,你是第1个使用timer的线程
t2,你是第2个使用timer的线程
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Java5 线程