线程(基础)
程序 program 简单来说就是我们写的代码
进程 正在运行中的程序
进程产生线程
单线程: 同一时刻,只允许执行一个线程
多线程:同一时刻,可以执行多个线程
并发:同一时刻,多个任务交替执行 ---------单核 cpu 实现的多任务就是并发
并行:同一时刻,多个任务同时执行 -----------多核 cpu 可以实现并行, 也可能并发和并行同时存在
package com.wxledu.threaduse;
/**
* @author 王鑫磊
* @version 1.0
* 演示通过继承 Thread 类创建进程
*/
public class Thread01 {
public static void main(String[] args) throws InterruptedException {
// 创建一个 cat 对象, 可以当做线程使用
Cat cat = new Cat();
// 启动线程
cat.start(); // 最终会执行 cat 的 run 方法
// 当 main 线程 启动一个子线程的时候,主线程不会阻塞,会继续执行
// 这时主线程和子线程交替执行
System.out.println("主线程不会阻塞,会继续执行" + Thread.currentThread().getName()); // 主线程的名字就叫 main
for (int i = 0; i < 10; i++) {
System.out.println(i);
Thread.sleep(1000); // 让主线程休眠
}
}
}
// 1. 当一个类继承了 Thread 类 该类就可以当做线程使用
// 2. 我们会重写 run 方法,写上自己的的业务代码
// 3. run Thread 类实现了 Runnable 接口的 run 方法
/*
@Override
public void run() {
if (target != null) {
target.run();
}
}
*/
class Cat extends Thread{
@Override
public void run() {
// 写上自己的额业务逻辑
int times = 0;
while(true){
// 每隔 1 s ,在控制台输出 “喵喵, 我是小猫咪”
System.out.println("喵喵, 我是小喵咪" + (++times) + " " + Thread.currentThread().getName());
// 让该线程休眠 1 s
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (times == 80){ // 如果输出了 8 次就退出
break;
}
}
}
}
实现 runnable 接口
说明:
java 是单继承,在某些情况下一个类可能已经继承了某个父类,在这个时候,用 Thread 类方法来实现创建线程显然就不可能了
java 设计者们提供了另外一种方式创建线程,就是通过 Runnable
接口的方式来创建线程
setName | 设置线程名称 |
---|---|
getName | 返回该线程的名称 |
start | 使该线程开始执行 |
run | 调用线程对象的 run 方法 |
setPriority | 更改线程的优先级 |
getPriority | 获得线程的优先级 |
sleep | 在指定的毫秒数内让当前正在执行的线程休眠 |
interrupt | 中断线程 |
用户线程和守护线程
用户线程:也叫工作线程,当线程的任务执行完或通知方式结束
守护线程: 一般为工作线程服务,当所有的用户线程结束,守护线程也就结束
常见的额守护线程 : 垃圾回收机制
上图是现成的生命周期
Synchronized 非公平锁
线程同步机制
- 在多线程编程中,一些敏感的个人数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任何同一时刻,最多只有一个线程访问,以保证数据的完整性
- 也可以这样理解:线程同步,即当有一个线程在对内存进行操作的时候,其他线程都不可以对这个内存的地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作
- 同步具体方法 - Synchronized
1) 同步代码块
synchronized (对象){ // 得到独像的锁, 才能操作同步代码
// 需要被同步的代码
}
2) synchronized 还可以放在方法声明中, 表示整个方法- 为实现同步
public synchronized void m (String name){
// 需要被同步的代码
}
3) 如何理解:就好像某小伙伴上厕所前先把,门关上(上锁) 完事后再出来(解锁), 那么其他小伙伴就可以在使用厕所了
4) 使用 Synchronized 解决售票问题 , 把对票数的操作封装到 一个方法中 用 Synchronized 进行声明
互斥锁
- Java 语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性
- 每个对象都对应于一个可称为 “ 互斥锁的标记” 这个标记保证在任意时刻,只能有一个线程访问对象
- 关键字
synchronized
来与对象的互斥锁联系, 当某个独像与synchronized
修饰时,表名该对象在唉任一时刻只能有一个线程访问 - 同步的局限性: 导致程序的执行效率降低
- 同步方法(非静态的) 的锁可以是 this 也可以是其他线程(要求是同一个对象)
- 同步方法(静态的) 的锁为当前类本身
- 注意事项和细节
- 同步方法如果没有使用 static 修饰: 默认锁对象就是 this
- 如果方法使用 static 修饰 ,默认锁的对象:当前类.class
- 实现落地步骤
- 需要先分析上锁代码
- 选择同步代码或同步方法
- 要求多个线程的锁对象为同一个即可
线程死锁
多个线程都占用了对方的锁资源,但不肯相让,导致了死锁,在编程时一定要避免死锁的发生
释放锁
- 什么情况下不会释放锁
- 线程执行同步代码块或者同步方法的时候,程序调用了
Thread.sleep()
Thread.yield()
暂停当前线程的执行不会释放锁 - 线程执行同步代码快的时候,其他线程调用了 该线程的
suppend()
方法,将该线程挂起,该线程不会被释放
提示:应尽量避免使用 supped() 和 resume() 来控制线程,方法不推荐使用
package com.wxledu.homework;
/**
* @author 王XX
* @version 1.0
*
* 要求
* 1. 有两个用户分别从 同一张卡里取钱(总额 : 10000)
* 2. 每次都取 1000 ,当余额不足时, 就不用取了
* 3. 不能出现超取现象 => 线程同步问题
*/
public class Homework {
public static void main(String[] args) {
T t = new T();
Thread thread1 = new Thread(t);
thread1.start();
Thread thread2 = new Thread(t);
thread2.start();
}
}
/*
class Qu extends Thread{
public static int money = 10000;
private static boolean loop = true;
public void setLoop(boolean loop){
this.loop =loop;
}
// 定义一个取钱方法, 因为有多个用户,取同一张卡上面的钱
public static synchronized void drawMoney(){
if (money <= 0){
System.out.println("当前余额不足,请改天来取");
loop = false;
return;
}
System.out.println(Thread.currentThread().getName() + "取了1000元,剩" + (money -= 1000));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
public void run() {
while(loop){
drawMoney();
}
}
}
*/
// 1. 多个线程同时共享访问同一变量, 实现 Runnable
class T implements Runnable{
private int money = 10000;
@Override
public void run() {
while (true){
// 多个线程互斥的对共享变量进行访问
synchronized (this){
if (money <= 0){
System.out.println("余额不足");
break;
}
money -= 1000;
System.out.println(Thread.currentThread().getName() + "取了 1000 元, 剩" + money);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
标签:同步,15,Thread,基础,线程,run,方法,public From: https://www.cnblogs.com/tomlove/p/17884206.html纸上得来终觉浅,绝知此事要躬行。