java学习笔记|多线程

Posted by wzc on 2020-01-15

java的多线程

线程的创建和启动:

image-20191211174436584

  • 继承Thread类;

  • 实现Runnable接口的类进行接口回调;

    image-20191211174640264

    代码示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //实现Runnable接口的类
    class RunClass implements Runnable{
    public void run(){
    for (int i=1; i<=20; i++)
    System.out.print("次" + i + ", ");
    }
    }
    public class TestImplementsRunnable{
    public static void main(String[] args){
    Thread sub = new Thread(new RunClass());
    sub.start();
    for (int i=1; i<=20; i++)
    System.out.print("主" + i + ", ");
    }
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    //继承Thread类
    class SubThread extends Thread{
    public void run(){
    for (int i=1; i<=20; i++)
    System.out.print("次" + i + ", ");
    }
    }
    public class TestExtendsThread{
    public static void main(String[] args){
    SubThread sub = new SubThread();
    sub.start();
    for (int i=1; i<=20; i++)
    System.out.print("主" + i + ", ");
    }
    }

线程的生命周期:

  • 产生

  • 存在(运行/中断)

    ​ 调用start方法运行

    ​ 中断类型:线程运行期间执行了sleep方法,必须使用interrupt才能被吵醒;线程运行期间执行了wait()方法,则这个线程中断,可以使用notify()或者notifyAll()结束等待

  • 消亡

线程的常用方法:

1
2
3
4
public static void sleep(int millis) throws InterruptedException
public final boolean isAlive()
public void interrupt()
public static Thread currentThread()

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
class Work implements Runnable 
{
Thread zhangWorker,wangWorker,boss;
Work()
{
boss=new Thread(this);
boss.setName("老板");

zhangWorker=new Thread(this);
zhangWorker.setName("张工");

wangWorker=new Thread(this);
wangWorker.setName("王工");
}

public void run()
{
int i=0;
int j=0;
if(Thread.currentThread()==zhangWorker)
{
while(true)
{
try{
i++;
System.out.println(zhangWorker.getName()+"已搬运了"+i+"箱苹果\n");
if(i==3)
return;
Thread.sleep(10000);
}catch(InterruptedException e){
System.out.println(boss.getName()+"让"+zhangWorker.getName()+"继续工作");
}
}
}
else if(Thread.currentThread()==wangWorker)
{
while(true)
{
try{
j++;
System.out.println(wangWorker.getName()+"已搬运了"+j+"箱香蕉\n");
if(j==3)
return;
Thread.sleep(10000);
}catch(InterruptedException e){
System.out.println(boss.getName()+"让"+wangWorker.getName()+"继续工作");
}
}
}
else if(Thread.currentThread()==boss)
{
while(true)
{
zhangWorker.interrupt();
wangWorker.interrupt();
if(!(wangWorker.isAlive()||zhangWorker.isAlive()))
{
System.out.printf(boss.getName()+"说:可以下班了");
return;
}
}
}
}
}
public class WorkExample
{
public static void main(String args[])
{
Work work=new Work();
work.zhangWorker.start();
work.wangWorker.start();
work.boss.start();
}
}

线程同步

关键字:synchronized

一个方法使用关键字synchronized修饰后,如果某个线程获得CPU的使用权去使用该方法,CPU会让它执行完同步方法中的所有任务,在这期间,CPU不会把时间片分配给其他也要使用同步方法的线程当一个线程在使用同步方法的过程中,需要借助其他线程才能完成任务时,可以在同步方法中使用wait()方法使本线程让出CPU的使用权,并允许其它线程使用这个同步方法
其他线程使用完同步方法之后,使用**notify()(正在等待的只有一个线程)或者notifyAll()**(正在等待的有多个线程)通知处于等待中的线程结束等待

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import java.util.*;
class RWthread
{
public static void main(String args[])
{
String readName="读线程",writeName="写线程";
ReadWrite rw=new ReadWrite(readName,writeName);
Thread read,write;
read=new Thread(rw);
write=new Thread(rw);
read.setName(readName);
write.setName(writeName);
read.start();
write.start();
}
}
class ReadWrite implements Runnable
{
String ID=null;
String name=null;
String readName,writeName;
boolean flag=false;
public ReadWrite(String s1,String s)
{
readName=s1;
writeName=s;
}
public void run()
{
readOrWrite();
}
public synchronized void readOrWrite() //同步方法
{
if(Thread.currentThread().getName().equals(readName))
{
Scanner reader=new Scanner(System.in);
while(true)
{
if(flag)
{
try{
wait();
}catch(InterruptedException e){}
}
System.out.println("请输入学号:");
ID=reader.nextLine();
if(ID.equals("finish"))
{
System.out.println("\n读线程和写线程工作结束!");
flag=true;
notify();
reader.close();
return;
}
System.out.println("请输入姓名:");
name=reader.nextLine();
flag=true;
notify();
}
}
else if(Thread.currentThread().getName().equals(writeName))
{
while(true)
{
if(!flag)
{
try{
wait();
}catch(InterruptedException e){}
}
if(ID.equals("finish"))
return;
System.out.println("\n输出学号:"+ID+",输出姓名:"+name);
System.out.println();
flag=false;
notify();
}
}
}
}


线程联合

线程thread1在运行期间联合线程thread2,语句如下(注意,是被联合的线程调用join方法):

thread2.join();

如果线程thread1在运行期间联合了线程thread2

image-20191211181313608

如果线程thread1联合线程thread2时,线程thread2已经消亡,则thread2.join()不会产生任何效果

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
class JoinThread implements Runnable 
{
Thread 运货司机,装运工,仓库管理员;
String step[]={"打开车锁","把握方向盘","挂挡","踩油门","开车"};

JoinThread()
{
运货司机=new Thread(this);
装运工=new Thread(this);
仓库管理员=new Thread(this);

运货司机.setName("运货司机");
装运工.setName("装运工");
仓库管理员.setName("仓库管理员");
}

public void run()
{
if(Thread.currentThread()==运货司机)
{
try{
Thread.sleep(1000);
}catch(InterruptedException ee){ }

System.out.println(运货司机.getName()+"等"+装运工.getName()+"装货");
装运工.start();

try{
装运工.join();
} catch(InterruptedException e) { }

for(int i=0;i<step.length;i++)
{
System.out.println(运货司机.getName()+step[i]);

try{
Thread.sleep(1000);
}catch(InterruptedException ee){ }
}
}
else if(Thread.currentThread()==装运工)
{
try{
Thread.sleep(1000);
}catch(InterruptedException ee){ }

System.out.println(装运工.getName()+"等"+仓库管理员.getName()+"开门");
仓库管理员.start();

try{
仓库管理员.join();
}catch(InterruptedException e){ }

for(int i=1;i<=10;i++)
{
System.out.println(装运工.getName()+"搬运第"+i+"箱货物到货车");
try{
Thread.sleep(1000);
}catch(InterruptedException ee){ }
}
}
else if(Thread.currentThread()==仓库管理员)
{
try{
Thread.sleep(1000);
}catch(InterruptedException ee){ }

for(int i=1;i<=5;i++)
{
System.out.println(仓库管理员.getName()+"打开第"+i+"道门") ;
try{
Thread.sleep(1000);
}catch(InterruptedException ee){ }
}
}
}
}
public class JoinExample
{
public static void main(String args[])
{
JoinThread a=new JoinThread();
a.运货司机.start();
}
}

守护线程

image-20191211182050511

例如java垃圾回收线程,当所有线程结束时,回收线程才能结束运行。