多线程Word下载.docx

上传人:b****5 文档编号:21306778 上传时间:2023-01-29 格式:DOCX 页数:61 大小:791.80KB
下载 相关 举报
多线程Word下载.docx_第1页
第1页 / 共61页
多线程Word下载.docx_第2页
第2页 / 共61页
多线程Word下载.docx_第3页
第3页 / 共61页
多线程Word下载.docx_第4页
第4页 / 共61页
多线程Word下载.docx_第5页
第5页 / 共61页
点击查看更多>>
下载资源
资源描述

多线程Word下载.docx

《多线程Word下载.docx》由会员分享,可在线阅读,更多相关《多线程Word下载.docx(61页珍藏版)》请在冰豆网上搜索。

多线程Word下载.docx

停止线程

stop(已废弃)

停止线程有stop方法,不过不要使用,太暴力,容易出现数据不一致等问题。

 

interrupt中断

中断线程通过调用线程的interrupt方法。

如果线程是RUNNABLE状态,则会对线程设置一个中断标志,然后实际的中断还是要程序中通过标志来判断自行处理。

publicstaticvoidmain(String[]args)throwsInterruptedException{

Threadt1=newThread(){

@Override

publicvoidrun(){

while(true){

Thread.yield();

}

}

};

t1.start();

Thread.sleep(2000);

t1.interrupt();

}

这里执行了t1.interrupt();

并不会让t1线程中断。

改成如下即可:

System.out.println("

kkk"

);

if(this.isInterrupted()){

break;

}

如果线程正在WAITING、TIME-WAITING状态,收到interrupt则会抛出InterruptedException异常,不会设置标志位。

而在BLOCKED状态则要区分,普通BLOCKED状态不会抛异常,如果是等待ReentrantLock的lockInterruptibly锁,则会抛出异常

状态切换

wait、notify、notifyAll

wait、notify、notifyAll是对象上的方法,一个线程调用了某个对象wait方法,当前线程会进入阻塞状态(WAITING),加入到对象的阻塞队列中,一个对象的阻塞队列可能有多个线程,调用对象的notify方法会从阻塞队列中随机唤醒一个线程,唤醒的线程会进入blocked状态,等待对象的锁,notifyAll会唤醒该对象阻塞队列的所有阻塞线程。

调用wait和notify方法前必须获得对象的锁,直接调用是不行的,如:

publicclassTest3{

Objecto=newObject();

o.wait();

}

会报错

所以一般都在synchronize中调用,改为如下即可:

synchronized(o){

o.wait();

}

唤醒的线程不会直接向下执行,而是进入blocked状态,等待拿到对象的锁以后才进入往下执行。

publicclassTest2{

staticObjecto=newObject();

try{

synchronized(o){

o.wait();

t1end"

}catch(InterruptedExceptione){

e.printStackTrace();

Thread.sleep(1000);

o.notify();

System.out.println("

t1notified"

Thread.sleep(2000);

mainend"

输出:

t1notified

mainend

t1end

其中t1唤醒之后并没有马上执行,而是等待主线程执行完synchronize方法释放锁以后才执行。

调用wait方法会释放当前的锁,而sleep方法不会释放锁。

suspend、resume(已废弃)

suspend会挂起线程,resume恢复线程,挂起的线程状态还是RUNNABLE,如下:

由于挂起线程代码一般是在本线程中执行,而线程挂起之后就能通过其他线程来执行恢复本线程的代码,而线程间的先后顺序往往不能保证,很容易导致resume先于suspend执行,这样挂起的线程就无法恢复了,所以此方式已被废弃使用。

join、yield

join等待一个线程执行完,本线程再执行,用于一个线程依赖另一个线程的执行结果的情况,如:

staticvolatileinta=0;

for(inti=0;

i<

1000000;

i++){

a++;

};

t1.join();

//等待t1线程累加完再打印a,否则打印的a可能会小于1000000

System.out.println(a);

//结果打印出1000000

yield会让线程从运行状态转为就绪状态,重新争夺CPU资源,用于优先级低的线程让出CPU资源。

volatile

见”jvm.docx”

线程组

把多个线程归成一个组,起个组名,统一管理。

ThreadGroupthreadGroup=newThreadGroup("

threadGroup"

Threadt1=newThread(threadGroup,"

t1"

){

try{

Thread.sleep(3000);

}catch(InterruptedExceptione){

e.printStackTrace();

System.out.println(this.getThreadGroup().getName()+"

-"

+this.getName());

Threadt2=newThread(threadGroup,"

t2"

t2.start();

threadGroup.list();

打印:

java.lang.ThreadGroup[name=threadGroup,maxpri=10]

Thread[t1,5,threadGroup]

Thread[t2,5,threadGroup]

threadGroup-t1

threadGroup-t2

……

守护线程

当一个Java应用内,所有非守护进程都结束时,Java虚拟机就会自然退出,守护线程自动结束

/**

*守护线程测试

*@authorAdministrator

*

*当一个Java应用内,所有非守护进程都结束时,Java虚拟机就会自然退出,守护线程自动结束

*

*/

publicclassDaemonThreadTest{

publicstaticclassDaemonThreadextendsThread{

@Override

publicvoidrun(){

start"

try{

Thread.sleep(2000);

}catch(InterruptedExceptione){

e.printStackTrace();

end"

//这句代码没有执行,因为主线程已经提前执行完了

DaemonThreaddt=newDaemonThread();

dt.setDaemon(true);

dt.start();

start

其中dt.setDaemon(true);

要先于start()方法,执行,否则抛出如下异常:

而线程会被当做非守护线程继续执行,此时打印了end。

线程优先级

优先级越高,争夺到CPU的概率越高。

*测试线程优先级,优先级高的线程先执行完的概率大

publicclassPriorityTest{

publicstaticclassHighextendsThread{

staticintcount=0;

while(true){

synchronized(PriorityTest.class){

count++;

if(count>

10000000){

System.out.println("

High"

publicstaticclassLowextendsThread{

Low"

Highhigh=newHigh();

Lowlow=newLow();

//设置线程优先级

high.setPriority(Thread.MAX_PRIORITY);

low.setPriority(Thread.MIN_PRIORITY);

low.start();

high.start();

多次试验之后High先执行完的概率高于Low

synchronized

注意:

不要锁Integer等包装对象,因为它的值一旦变化,就会自动创建一个新对象。

ArrayList、HashMap的并发问题

Vector、ConcurrentHashMap是线程安全的

队列

概念

Queue是jdk1.5以后提供的队列接口,与List、Set平级,都是Collection的子接口

Queue队列先进先出,从队尾进,队首出。

队列的方法:

add、offer都是入列,队列满时,add抛出异常,offer返回false。

remove、poll都是出列,返回出列的值,队列空时,remove抛出异常,poll返回null

element、peek都是返回队首值,不出列,队列空时,element抛出异常,peek返回null

ps:

由于poll和peek方法出错就返回null。

因此,尽量不要向队列插入null值。

使用,如:

publicclassQueueTest{

publicstaticvoidmain(String[]args){

//add()和remove()方法在失败的时候会抛出异常(不推荐)

Queue<

String>

queue=newLinkedList<

();

//添加元素(入列)

queue.offer("

a"

//如果队列已满,返回false

queue.add("

b"

//如果队列已满,会抛出异常

for(Stringq:

queue){

System.out.println(q);

//获取第一个元素,不删除

System.out.println("

peek="

+queue.peek());

//返回第一个元素,队列如果为空,返回null

//遍历队列

//删除元素(出列)

poll1="

+queue.poll());

//返回第一个元素,并在队列中删除,如果队列为空,返回null

poll2="

+queue.remove());

//返回第一个元素,并在队列中删除,果队列为空,返回抛出异常

poll3="

//队列为空,返回null

element="

+queue.element());

//返回第一个元素,队列如果为空,抛出异常

Queue的子类

Queue有许多实现,如:

双向队列Deque

双向队列,提供addFirst、addLast、offerFirst、offerLast等可以从队首队尾操作的方法。

线程安全队列ConcurrentLinkedQueue

采用无锁的volatile做的,效率很高

阻塞队列BlockingQueue(线程安全)

实现阻塞接口BlockingQueue的队列,如:

ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、DelayQueue

阻塞队列是线程安全的,内部用ReentrantLock保证,如:

阻塞接口的Queue有put入列,take出列,put时如果队列已满,会阻塞等待,take时队列如果为空,也会阻塞等待。

通常用于生产者、消费者模式。

ArrayBlockingQueue:

创建时必须指定大小。

LinkedBlockingQueue:

创建时可不指定大小,如果没有指定大小,则put时,只有容量达到Integer.MAX_VALUE才会阻塞。

*阻塞队列测试

staticBlockingQueue<

Integer>

blockingQueue=newArrayBlockingQueue<

(2);

newThread(newRunnable(){

Thread.sleep(2000);

//新线程启动后先sleep2秒。

blockingQueue.put(123);

branchthreadend"

}catch(Exceptione){

}).start();

//take空队列会阻塞当前线程,等待队列put完后才继续执行

blockingQueue.take();

mainthreadend"

branchthreadend

mainthreadend

SynchronousQueue

一种特殊的BlockingQueue,put和take必须交替执行,其中每个put必须等待一个take,反之亦然。

*iterator()永远返回空,因为里面没东西。

*peek()永远返回null。

*put()往queue放进去一个element以后就一直wait直到有其他thread进来把这个element取走。

*offer()往queue里放一个element后立即返回,如果碰巧这个element被另一个thread取走了,offer方法返回true,认为offer成功;

否则返回false。

*offer(2000,TimeUnit.SECONDS)往queue里放一个element但是等待指定的时间后才返回,返回的逻辑和offer()方法一样。

*take()取出并且remove掉queue里的element(认为是在queue里的。

),取不到东西他会一直等。

*poll()取出并且remove掉queue里的element(认为是在queue里的。

),只有到碰巧另外一个线程正在往queue里offer数据或者put数据的时候,该方法才会取到东西。

否则立即返回null。

*poll(2000,TimeUnit.SECONDS)等待指定的时间然后取出并且remove掉queue里的element,其实就是再等其他的thread来往里塞。

*isEmpty()永远是true。

*remainingCapacity()永远是0。

*remove()和removeAll()永远是false。

优先级队列PriorityQueue

每次入列,整个队列都会重新排序,出列时按排序后的顺序出列,不能有null元素(会抛空指针异常),使用如:

*优先级列队测试

publicstaticvoidmain(String[]args)throwsInterruptedExcepti

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

当前位置:首页 > 解决方案 > 解决方案

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1