多线程详细笔记含代码.docx

上传人:b****6 文档编号:8741876 上传时间:2023-05-14 格式:DOCX 页数:14 大小:347.32KB
下载 相关 举报
多线程详细笔记含代码.docx_第1页
第1页 / 共14页
多线程详细笔记含代码.docx_第2页
第2页 / 共14页
多线程详细笔记含代码.docx_第3页
第3页 / 共14页
多线程详细笔记含代码.docx_第4页
第4页 / 共14页
多线程详细笔记含代码.docx_第5页
第5页 / 共14页
多线程详细笔记含代码.docx_第6页
第6页 / 共14页
多线程详细笔记含代码.docx_第7页
第7页 / 共14页
多线程详细笔记含代码.docx_第8页
第8页 / 共14页
多线程详细笔记含代码.docx_第9页
第9页 / 共14页
多线程详细笔记含代码.docx_第10页
第10页 / 共14页
多线程详细笔记含代码.docx_第11页
第11页 / 共14页
多线程详细笔记含代码.docx_第12页
第12页 / 共14页
多线程详细笔记含代码.docx_第13页
第13页 / 共14页
多线程详细笔记含代码.docx_第14页
第14页 / 共14页
亲,该文档总共14页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

多线程详细笔记含代码.docx

《多线程详细笔记含代码.docx》由会员分享,可在线阅读,更多相关《多线程详细笔记含代码.docx(14页珍藏版)》请在冰点文库上搜索。

多线程详细笔记含代码.docx

多线程详细笔记含代码

java知识点总结

@多进程

1.基本概念:

程序、进程、线程

程序(program):

一组指令的集合,一段静态代码。

(完成特定任务的代码,由某种语言编写)

进程(process):

是一个程序的执行过程(即正在运行的程序)。

是个动态过程:

有他自身的产生、存在和消亡的过程。

PS:

例子:

如运行中的QQ,运行中的MP3播放器。

程序和进程区别:

程序时静态的,进程是动态的。

线程(thread):

进程可细分为线程,是一个程序内部的一条执行路径

PS:

若一个程序可同一时间执行多个线程,就是支持多线程的

何时需要多线程:

[1]程序需要同时执行多个任务;

[2]程序需要实现一些需要等待的任务的时候(如用户输入、文件读写操作、网络操作、搜索等。

);

[3]需要一些后台运行的程序时-守护线程。

(如垃圾回收线程)

2.多线程的创建和使用

(1)线程的创建(2种方法)

[1]第一种创建:

继承于java.lang.Thread类(无需插包)

例子:

//1.创建一个继承于Thread的类

classSubThreadextendsThread{

publicvoidrun(){//2.重写Thread类的run()方法,方法内实现子线程内要完成的功能

for(inti=0;i<100;i++){

System.out.println(i);

}

}

}

publicclassTestThread{

publicstaticvoidmain(String[]args){

SubThreadst=newSubThread();//3.创建一个子类对象

st.start();//4.调用线程的start()方法(两个作用:

启用此线程,调用相应的run方法)

}

}

注意:

Thread类常用的方法及作用

-1-start()方法。

启动线程并执行相应的run方法

-2-run()方法。

子线程要执行的代码放到run()方法中

-3-currentThread()。

静态的,调用当前线程(相当于一个当前线程的对象,都是在自己的线程里才用的)。

(读音:

克(饿)‘润特)

-4-getName()方法。

获得此线程的名字

-5-setName()方法。

设置此线程的名字

-6-yield()方法。

CPU暂时释放该线程的执行权(也可能在下一次抢到执行权)(读音:

亿奥的)

-7-join()方法(该方法有异常,需要trycatch,使用的时候都是调用其他线程,st1.join())。

在A线程调用B线程的join方法时,A线停止运行,直至B线程执行结束,A线程再接着join之后的方法继续执行。

-8-isAlive()方法。

判断当前线程是否还存活(返回时布尔值)。

-9-sleep(longa)方法(需要抛trycatch异常)。

显示让当前线程睡眠a毫秒。

-10-线程通信:

wait()、notify()、notifyAll()

线程优先级的方法(优先级大的线程抢到CPU的概率大点)

-11-setPriority():

设置线程优先级(最小1,最大10(也可表示Thread.MAX_PRIORITY),正常5)(读音:

破ruai欧瑞踢)

-12-getPriority():

返回线程优先值

例子

#例子1:

currentThread()、getName()、setName()

classSubThread1extendsThread{

publicvoiarun(){

for(inti=0;i<10;i++){

System.out.println(Thread.currentThread().getName()+”:

”+i);//调用当前线程的名字,当前线程是st1

}

}

}

publicclassTestThread1{

publicstaticvoidmain(String[]args){

SubThread1st1=newSubTread1();

st1.setName(“子线程1”);//设置线程st1的名字

st1.start();//开始st1线程

Thread.currentThread().setName(“主线程”);//设置当前线程的名字(当前线程时主线程)

for(inti=0;i<10;i++){

System.out.println(Thread.crrentThread().getName()+”:

”+i);

}

}

}

#例子2:

yield()

 

classSubThread1extendsThread{

publicvoiarun(){

for(inti=0;i<10;i++){

System.out.println(Thread.currentThread().getName()+”:

”+i);

}

}

}

publicclassTestThread1{

publicstaticvoidmain(String[]args){

SubThread1st1=newSubTread1();

st1.setName(“子线程1”);

st1.start();

Thread.currentThread().setName(“主线程”);

for(inti=0;i<10;i++){

System.out.println(Thread.crrentThread().getName()+”:

”+i);

if(i%10==0){

Thread.crrentThread().yield();//当i是10的倍数的时候,主线程暂时释放CPU的执行权

}

}

}

}

#例子3:

join(),该方法有异常,需要trycatch

classSubThread1extendsThread{

publicvoiarun(){

for(inti=0;i<10;i++){

System.out.println(Thread.currentThread().getName()+”:

”+i);

}

}

}

publicclassTestThread1{

publicstaticvoidmain(String[]args){

SubThread1st1=newSubTread1();

st1.setName(“子线程1”);

st1.start();

Thread.currentThread().setName(“主线程”);

for(inti=0;i<10;i++){

System.out.println(Thread.crrentThread().getName()+”:

”+i);

if(i==20){/*当i等于20的时候,当前线程(主线程)停止运行,并运行线

程st1,当st1运行结束,继续运行主线程*/

try{

st1.join();

}catch(InterrupterExceptione){

e.printStackTrace();

}

}

}

}

}

#例子4:

isAlive()

classSubThread1extendsThread{

publicvoiarun(){

for(inti=0;i<10;i++){

System.out.println(Thread.currentThread().getName()+”:

”+i);

}

}

}

publicclassTestThread1{

publicstaticvoidmain(String[]args){

SubThread1st1=newSubTread1();

st1.setName(“子线程1”);

st1.start();

Thread.currentThread().setName(“主线程”);

for(inti=0;i<10;i++){

System.out.println(Thread.crrentThread().getName()+”:

”+i);

if(i==20){/*当i等于20的时候,当前线程(主线程)停止运行,并运行线

程st1,当st1运行结束,继续运行主线程*/

try{

st1.join();

}catch(InterrupterExcptione){

e.printstackTrace();

}

}

}

System.out.println(st1.isAlive());//判断线程st1是否还存活(当前结果是否);

}

}

 

#例子5:

sleep(longa),需要抛trycatch异常

classSubThread1extendsThread{

publicvoiarun(){

for(inti=0;i<10;i++){

System.out.println(Thread.currentThread().getName()+”:

”+i);

try{

Thread.sleep(1000);//当线程没执行一次for循环睡眠1000毫秒

}catch(InterruptedExceptione){

e.printStackTrace();

}

}

}

}

publicclassTestThread1{

publicstaticvoidmain(String[]args){

SubThread1st1=newSubTread1();

st1.setName(“线程1”);

st2.setName(“线程2”);

st1.start();

st2.start();

}

}

#例子6:

设置优先级

classSubThread1extendsThread{

publicvoiarun(){

for(inti=0;i<10;i++){

System.out.println(Thread.currentThread().getName()+”:

”+i);//调用当前线程的名字,当前线程是st1

}

}

}

publicclassTestThread1{

publicstaticvoidmain(String[]args){

SubThread1st1=newSubTread1();

st1.setPriority(Thread.MAX_PRIORITY);//设置线程st1的优先级为最大,即10

st1.setName(“子线程1”);

st1.start();

Thread.currentThread().setName(“主线程”);

for(inti=0;i<10;i++){

System.out.println(Thread.crrentThread().getName()+”:

”+i);

}

}

}

 

 

[2]第二种创建:

实现Runnable接口

classThread2implementsRunnable{//1.创建一个类实现Runnable接口

publicvoidrun(){//2.实现接口的抽象方法run方法

//子线程执行的代码

for(inti=1;i<=100;i++){

System.out.println(Thread.currentThread().getName+”:

”+i);

}

}

}

publicclassTestThread2{

publicstaticvoidmain(String[]args){

Thread2th=newThread2();//3.创建一个Runnable接口的实现类的对象

Threadthread1=newThread(th,”线程1”);/*4.创建一个Thread类的对象,并将Runnable实现类的对象加入到构造器中,

此时创建的Thread对象即为一个线程

*/

Threadthread2=newThread(th,”线程2”);//启动线程;过程:

执行Thread对象生成时构造器形参的对象的run方法

Threadthread3=newThread(th,”线程3”);

thread1.start();//5.调用Thread的start方法,启动线程

thread2.start();

thread3.start();

}

}

 

(2)线程创建方法之继成和实现的区别

[1]联系:

publicclassThreadimplementsRunnable{}

[2]哪种方式好?

为什么

实现优于继承

原因:

1.避免了java单继承的局限性

2.如果多线程操作同一份资源(不过可能存在一些线程安全问题),更适合使用实现的方式

3.线程安全问题

(1)存在的原因

由于一个线程在操作共享数据的过程中,未完毕的情况下,另外的线程也参与进来,导致共享数据存在了安全问题

 

(2)如何解决:

-1-解决原理:

必须让一个线程操作完毕共享数据后,其他线程才有机会操作共享数据

-2-java中解决线程安全的方式:

线程同步机制。

(以下两种方法解决)

[1]方法一:

同步代码块

-1-语法格式:

synchronized(同步监视器){(读音:

sing克瑞耐zed)

//需要被同步的代码(即为操作共享数据的代码,这里需要特别注意)

-2-使用场景和锁的使用:

^1.共享数据多线程共同操作一个数据(变量)

^2.同步监视器(即锁):

由任意一个类的对象来充当(不过在所有线程中,本对象必须只能

有一个),哪个线程获得此监视器,谁就执行大括号里被同步的代码。

俗称:

锁。

要求所有

线程必须使用同一把锁。

(例子如下)

运行结果如下:

 

PS:

实现this,继承慎用:

在通过实现Runnable创建线程时,可以用this作为同步监视器,但是通过继承Thread类来创建线程,慎用this(如果创建的类对象只有一个时可以用,不然不可以用)

 

[2]方法二:

同步方法(例子如下图)

过程:

将操作共享数据的方法声明为synchronized。

此方法为同步方法,能够保证其中一个线程执行此方法时,其他线程在外等待直至此线程执行完此方法。

同步方法的锁是:

当前this。

 

注意:

不管是同步代码块还是同步方法,synchronized所包含的内容必须是共享数据部分,不能多也不能上,比如上述例子,多了sleep一段代码块运行时就只执行线程1了。

4.线程的生命周期

线程和进程一样分为五个阶段:

创建、就绪、运行、阻塞、终止

 

补充:

1.wait阻塞,sleep、yield不阻塞:

调用wait方法可以让线程进入阻塞状态。

注意sleep和yield方法不能让线程进入阻塞状态。

//本句看法有疑问

2.线程安全问题总结:

线程在调用run方法运行的时候,当别的线程过来抢占CUP执行权的时候,原来的线程可能程序还未执行完,并进入就绪状态,这就导致了线程安全问题。

 

5.线程的通信

同步锁

 

ps:

每个java程序都有一个隐含的主线程:

main方法

和一个垃圾回收线程(守护线程,不会显现出来,但在后台运行)

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

当前位置:首页 > IT计算机 > 电脑基础知识

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

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