我的网站:欢迎大家访问
接着上一篇讲,现在来看看Thread类和线程同步问题,线程同步问题是很重要的一个知识点
Thread类
线程休眠
什么是线程休眠
?
线程类Thread当中有一个static void sleep(long millis)方法,在指定的毫秒数内让当前正在执行的线程休眠
语法:
在需要休眠的线程中输入Thread.sleep(想要休眠的时间,单位:毫秒);
?线程同步问题(重要)
同步代码(尤为重要)
基本语法结构
synchronized (同步监听对象) {
可能引发线程安全问题的代码
}
上面的结构相当于把{ }中的代码捆绑成一个整体,线程只能够一个一个的进来,执行完一个,下一 个才能进来
Demo
自定义线程类_09MyThread
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--; // 让票数递减
}
}
}
测试主类
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
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--; // 让票数递减
}
}
}
测试主类
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
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(); //关锁
}
}
}
}
测试主类
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();
}
}