Java多线程详解(二)

接着上一篇讲,现在来看看Thread类和线程同步问题,线程同步问题是很重要的一个知识点

Thread类

线程休眠

什么是线程休眠?

线程类Thread当中有一个static void sleep(long millis)方法,在指定的毫秒数内让当前正在执行的线程休眠

语法:

在需要休眠的线程中输入Thread.sleep(想要休眠的时间,单位:毫秒);

😭线程同步问题(重要)

同步代码(尤为重要)

基本语法结构

synchronized (同步监听对象) {

​ 可能引发线程安全问题的代码

}

上面的结构相当于把{ }中的代码捆绑成一个整体,线程只能够一个一个的进来,执行完一个,下一 个才能进来

Demo

自定义线程类_09MyThread

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
package com.ifueen.classdemo._09setNameRunnable_sync_code;

/*
* 用implements Runnable的方式来实现线程同步
* Thread.currentThread().getName() 获得当前对象的引用并获取名字
*
* 当前类的字节码对象MyThread.class
* synchronized (new Object()) 每次访问都有新的
* Object obj = new Object(); 可以
* static Object obj = new Object(); 可以
*
* */

public class _09MyThread implements Runnable {
static int num = 50; // 定义静态变量,让票数成为共享

@Override
public void run() { // 覆写run
// TODO Auto-generated method stub
while (num > 0) {
synchronized (this) { // 给我锁住! this也可以因为MyThread mt = new
// MyThread(); 只new了一份
safe(); //调用方法
}
}
}

private void safe() {
if (num > 0) {
System.out.println(Thread.currentThread().getName() + "您的票号是:" + num); // 输出
num--; // 让票数递减
}
}

}

测试主类

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
package com.ifueen.classdemo._09setNameRunnable_sync_code;

public class _09Test {
/*
* 实现线程的第二种方式,自定义类 implements Runnable
*
* 注意:接口实现方式,字段,没有加static也已经共享了,因为我们只创建了一个mt对象
*
*/
public static void main(String[] args) {
// TODO Auto-generated method stub

_09MyThread mt = new _09MyThread(); //实例化自定义的对象

Thread th1 = new Thread(mt); //实例化线程对象
Thread th2 = new Thread(mt);
Thread th3 = new Thread(mt);

th1.setName("警察先生"); //给线程对象传入Name的值
th2.setName("保安先生");
th3.setName("护士小姐");

th1.start(); //启动线程
th2.start();
th3.start();

}

}

同步方法

1、就是在需要被同步的方法上面加关键字 synchronized

2、加的位置 :在返回值类型的前面

3、不需要也不能够显示的写同步监听对象

4、如果是一个非static的方法,那么同步监听对象就是this;

5、如果是static修饰的方法,那么同步监听对象就是当前方法所在的类的字节码对象

Demo

自定义线程类MyThread

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
package com.ifueen.classdemo._11sync_method_Runnable;

/*
* implements Runnable方式来实现同步方法
*
* */

public class _11MyThread implements Runnable {
int num = 50; // 设置票池,不需要定义为共享

@Override
public void run() { // 覆写run
// TODO Auto-generated method stub
while (num > 0) {
safe(); //调用同步方法
}
}

private synchronized void safe() {
if (num > 0) {
try {
Thread.sleep(1000); //设置延迟1000ms
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "您的票号是:" + num); // 输出
num--; // 让票数递减
}
}

}

测试主类

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
package com.ifueen.classdemo._11sync_method_Runnable;

public class _11Test {
/*
* 实现线程的第二种方式,自定义类 implements Runnable
*
* 注意:接口实现方式,字段,没有加static也已经共享了,因为我们只创建了一个mt对象
*
*/
public static void main(String[] args) {
// TODO Auto-generated method stub

_11MyThread mt = new _11MyThread(); //实例化自定义的对象

Thread th1 = new Thread(mt); //实例化线程对象
Thread th2 = new Thread(mt);
Thread th3 = new Thread(mt);

th1.setName("警察先生"); //给线程对象传入Name的值
th2.setName("保安先生");
th3.setName("护士小姐");

th1.start(); //启动线程
th2.start();
th3.start();

}

}

锁机制

语法:

lock() 表示开始上锁了

ReentrantLock r = new ReentrantLock();

​ r.lock();

​ try {

​ // access the resource protected by this lock

​ } finally {

​ r.unlock();

Demo

自定义线程类MyThread

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
package com.ifueen.classdemo._13Lock_code_Runnable;

import java.util.concurrent.locks.ReentrantLock;

/*
* implements Runnable方式来实现同步方法
*
* */

public class _13MyThread implements Runnable {
int num = 50; // 设置票池,不需要定义为共享
ReentrantLock r = new ReentrantLock(); //实例化锁的对象
@Override
public void run() { // 覆写run
// TODO Auto-generated method stub
while (num > 0) {
r.lock(); //开启锁
try {
if (num > 0) {
System.out.println(Thread.currentThread().getName()+"您要购买的票只剩下"+num+"张啦");
num--;
}
} finally {
// TODO: handle finally clause
r.unlock(); //关锁
}
}
}


}

测试主类

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
package com.ifueen.classdemo._13Lock_code_Runnable;

public class _13Test {
/*
* 实现线程的第二种方式,自定义类 implements Runnable
*
* 注意:接口实现方式,字段,没有加static也已经共享了,因为我们只创建了一个mt对象
*
*/
public static void main(String[] args) {
// TODO Auto-generated method stub

_13MyThread mt = new _13MyThread(); //实例化自定义的对象

Thread th1 = new Thread(mt); //实例化线程对象
Thread th2 = new Thread(mt);
Thread th3 = new Thread(mt);

th1.setName("警察先生"); //给线程对象传入Name的值
th2.setName("保安先生");
th3.setName("护士小姐");

th1.start(); //启动线程
th2.start();
th3.start();

}

}
❤赏点钱让我买杯快乐水8❤