Thread.docx

上传人:b****2 文档编号:720869 上传时间:2023-04-29 格式:DOCX 页数:8 大小:78.33KB
下载 相关 举报
Thread.docx_第1页
第1页 / 共8页
Thread.docx_第2页
第2页 / 共8页
Thread.docx_第3页
第3页 / 共8页
Thread.docx_第4页
第4页 / 共8页
Thread.docx_第5页
第5页 / 共8页
Thread.docx_第6页
第6页 / 共8页
Thread.docx_第7页
第7页 / 共8页
Thread.docx_第8页
第8页 / 共8页
亲,该文档总共8页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

Thread.docx

《Thread.docx》由会员分享,可在线阅读,更多相关《Thread.docx(8页珍藏版)》请在冰点文库上搜索。

Thread.docx

Thread

线程

(一)

在java.lang.Thread包中

Thread类由jdk提供,用于封装对jvm中线程的控制

使用线程的一些原因是它们可以帮助:

∙利用多处理器系统

∙简化建模

∙执行异步或后台处理

一、创建一个线程知识点:

jvm会默认创建一个线程叫主线程(main),用来运行主方法,程序员可以自定义线程

线程是一个抽象的概念,我们将线程理解为就是一个任务

一个进程中可以有多个线程

1、进程中的多任务

2、线程的基本创建方式:

写一个类继承Tread,重写run方法,这个方法要指定线程的运行体

publicstatic

publicvoidrun(){

…..

}

Threadt=newThread();

t.start();

Thread.sleep(longl):

静态方法,不需要new对象,直接类名点调用

作用:

让当前线程挂起,挂起l毫秒(让运行该线程的线程挂起)

如:

Thread.sleep(1000);//是由主线程运行的,所以主线程运行到这,休息一秒,让创建的子方法运行

在一个线程对新线程的Thread对象调用start()方法之前,这个新线程并没有真正开始执行。

Thread对象在其线程真正启动之前就已经存在了,而且其线程退出之后仍然存在。

这可以让您控制

或获取关于已创建的线程的信息,即使线程还没有启动或已经完成了。

线程会以以下三种方式之一结束:

∙线程到达其run()方法的末尾。

∙线程抛出一个未捕获到的Exception或Error。

∙另一个线程调用一个弃用的stop()方法。

弃用是指这些方法仍然存在,但是您不应该在新代码中使用它们,并且应该尽量从现有代码中除去它们。

当Java程序中的所有线程都完成时,程序就退出了。

ThreadAPI包含了等待另一个线程完成的方法:

join()方法。

当调用Thread.join()时,调用线程将阻塞,直到目标线程完成为止。

Thread.join()通常由使用线程的程序使用,以将大问题划分成许多小问题,每个小问题分配一个线程

二、线程状态图:

重点(线程启动之后的状态)

1、线程有7个状态:

1、New:

新建

2、Ready:

就绪每个新建的线程只能start()一次

3、Running:

运行一个就绪的线程只能运行,他的运行由线程调度器来管理。

一个正在运行的线程除了NEW去不了其他的线程状态都可以去。

Yield可以让运行的线程回到就绪或者CPU事件片用完也可以让他回到就绪

4、Dead:

死亡Run(){}结束后本线程结束。

未捕获异常也会结束本线程。

线程一旦销往永远不可逆。

5、Blocked阻塞,阻塞的线程不能运行。

Sleep,join,等待用回输入(如scanner)都可以进入阻塞状态.阻塞的状态接触阻塞将会进入就绪。

当Sleep的事件到了后就会接触阻塞,JOIN也是时间到了就会解除阻塞,等待用回输入等提交后解除阻塞。

6、对象锁池,同步的线程在对象锁池等待。

Q;怎样的线程进入对象锁池:

A;1.只要遇到同步语句快2.没有对象锁

7、等待池

2、线程的状态及其转换

就绪----cpu调度---->运行

运行----cpu调度---->就绪注意:

正在运行的线程只有一个,但等待的线程可以有多个

运行--------------->阻塞由于某种原因不能再运行,出现阻塞状态如:

等待用户输入(资源),或者调用sleep方法。

必须等(线程别挂起)到资源到来,或者时间片到了

阻塞---------------->就绪条件到来时,会变到就绪状态,(等待cpu空闲才能别调度)

注意:

图中标记依次为

①输入完毕;②wakeup③t1退出

⑴如等待输入(输入设备进行处理,而CUP不处理),则放入阻塞,直到输入完毕。

⑵线程休眠sleep()

⑶t1.join()指停止main(),然后在某段时间内将t1加入运行队列,直到t1退出,main()才结束。

特别注意:

①②③与⑴⑵⑶是一一对应的。

进程的休眠:

Threadsleep(1000);//括号中以毫秒为单位

当main()运行完毕,即使在结束时时间片还没有用完,CPU也放弃此时间片,继续运行其他程序。

Try{Thread.sleep(1000);}

Catch(Exceptione){e.printStackTrace(e);}

T1.join()表示运行线程放弃执行权,进入阻塞状态。

当t1结束时,main()可以重新进入运行状态。

T1.join实际上是把并发的线程编程并行运行。

线程的优先级:

1-10,越大优先级越高,优先级越高被OS选中的可能性就越大。

(不建议使用,因为不同操作系统的优先级并不相同,使得程序不具备跨平台性,这种优先级只是粗略地划分)。

注:

程序的跨平台性:

除了能够运行,还必须保证运行的结果。

一个使用yield()就马上交出执行权,回到可运行状态,等待OS的再次调用

3、守护线程

t.setDaemon(true);//设置守护线程

主线程结束后守护线程也就结束了

通过setDaemon方法,可以设置线程为守护线程。

JVM如果发现当前的线程全部是守护线程时,就退出

如:

出题程序中计时线程应该为守护线程

4、Runnable接口

为什么要使用Runnable接口?

使用这种实现接口的机制,来解决Java语言不支持的多重继承的问题。

Runnable接口提供了run()方法的原型,因此,在希望定制的线程类中,只要实现此接口,也就是只要用特定的行为实现Runnable接口中的run()方法,即可实现新线程类的运行行为。

三、我们创建线程有两种方法:

1、写一个MyThreadextendsThread;Threadt=newMyThread();

线程的运行体是:

MyThread的Run()方法

eg.继承Thread

publicclassMyThread_1extendsThread

{

publicvoidrun()

{

//somecode

}

}

当使用继承创建线程,这样启动线程:

newMyThread_1().start()

2、Threadt=newThread(r);其中r是实现了Runnable接口的类的对象

classSomeClassimplementsRunnable{publicvoidrun(){...}}

Threadt=newThread(r);

使用Runnable接口,保证这个对象体一定有run方法

publicvoidrun(){

}

}

eg.实现Runnable接口

publicclassMyThread_2implementsRunnable

{

publicvoidrun()

{

//somecode

}

}

当使用实现接口创建线程,这样启动线程:

newThread(newMyThread_2()).start()

注意,其实是创建一个线程实例,并以实现了Runnable接口的类为参数传入这个实例,当执行这个线程的时候,MyThread_2中run里面的代码将被执行。

6、两个以上的线程去访问同一个(可变)对象,就有可能出现线程安全问题

我们使用加锁机制,保证一个线程去修改对象时,另一个线程不可以访问对象

同步方法:

synchronized难,但必须要掌握:

语法格式:

Synchronizedvoidmethod(){}

Synchronized在方法的前面

Voidmethod(){

Synchronized(Object){他后面不一定放THIS任何对象都可以

语句块

}

}

让这个对象看住这个语句块,某一时刻只允许一个线程来访问一个语句块

使用方法:

object只有一把钥匙,只有拿到这边钥匙,才能执行被{}框起来的语句块,其他的线程来了,就只能等待这把钥匙。

刚才拿到钥匙的线程处理时就必须归还钥匙

注意:

1、{}要括哪些代码

2、谁来看语句块

publicclassABC{

privateListlist...

publicvoidaddToList(){

....

}

syncronized(newDate()){//这样每次加载一次程序,就会创建一个新的对象,不可以使用这个对象来看,我们使用一个固定的(不可变的)对象,可以使用list即this本对象

list.add(....){

}

}

问:

这个类是否是线程安全的?

也就是问如果有两个以上的线程去使用该类的同一个对象,是否会有线程安全问题

如:

也不可以是一个调用addList(),一个调用remove()方法

怎样将这个类变成线程安全的?

不安全的因素在:

一个调用addList(),一个调用remove()方法,我们采取加锁的方法,要考虑加锁的范围,这样可以提高效率,在这里我们只有将list.add(n)和list.move(n);

各自放入到synchronized中,这个对象就是list本身,(如monitor),当然如果我们自己定义了一个Object对象来看门的话,会出现add和remove可以同时进,(list来看add,Object看remove),所以我们将这两个对方使用同一个对象来看,只有一个monitor

注意:

1、publicvoidf(){

syncronized(this){//使用this看门并且所有的方法全部括起来

.....

}

}

等同于:

publicsynchronizedvoidf(){

.....

}

2、PushThreadt1=newPushThread();不算线程

Threadt2=newThread();是线程

7、了解线程的一些基本方法:

使用getName来线程标识。

t.getName

getId,是唯一的,线程编号不能改,所以没有setId

t.setPriority(newPriority);//设置优先级,数目越大的,线程的优先级越高

一般情况不要去改优先级,默认主线程的优先级为5

因为由于垃圾回收机制比较高

我们一般创建线程的优先级最后不要超过5

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2