如果你认识从前的我,也许会原谅现在的我。

Ritchie里其

园龄:2年6个月粉丝:4关注:7

线程、锁Synchronized

一、守护线程(Daemon Thread)

1.1 简介

比如垃圾回收线程,就是最典型的守护线程。

Java程序入口就是由JVM启动main线程,main线程又可以启动其他线程。当所有线程都运行结束时,JVM退出,进程结束。

如果有一个线程没有退出,JVM进程就不会退出。所以,必须保证所有线程都能及时结束。

但是有一种线程的目的就是无限循环,例如,一个定时触发任务的线程:

如果这个线程不结束,JVM进程就无法结束。问题是,由谁负责结束这个线程?

然而这类线程经常没有负责人来负责结束它们。但是,当其他线程结束时,JVM进程又必须要结束,怎么办?

答案是使用守护线程(Daemon Thread)。

守护线程是指为其他线程服务的线程。在JVM中,所有非守护线程都执行完毕后,无论有没有守护线程,虚拟机都会自动退出。

因此,JVM退出时,不必关心守护线程是否已结束。

如何创建守护线程呢?方法和普通线程一样,只是在调用`start()`方法前,调用`setDaemon(true)`把该线程标记为守护线程:
在守护线程中,编写代码要注意:守护线程不能持有任何需要关闭的资源,例如打开文件等,因为虚拟机退出时,守护线程没有任何机会来关闭文件,这会导致数据丢失。

1.2 方法

方法名称 方法描述
public fifinal void setDaemon(boolean on) 将该线程标记为守护线程或用户线程(为true)
public fifinal boolean isDaemon() 测试该线程是否为守护线程

1.3 创建线程的2种方法:

  1. 继承Thread类,重写run方法,实例化线程对象,调用start()方法,因为java是单继承,这种方法不适合共享资源

  2. 实现Runnable接口,重写run方法,实例化实现了接口的对象,实例化线程对象,调用start()方法,是一种代理模式

Thread是实现了Runnable接口的类,使用run支持多线程。无论使用Runnable还是Thread,都会new Thread,然后执行run方法。
start0()方法是底层方法,由JVM调用,真正实现多线程。
run方法是一个普通的方法,没有真正启动一个线程。

1.4 使用内部类的方式来创建线程

package com.xxx;
public class Test01 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}).start();
new Thread(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}.start();
}
}

二、线程通信

wait⽅法与notify⽅法必须要在同步代码块或同步函数中使用,并由同⼀个锁对象调⽤。

wait⽅法与notify⽅法是属于Object类的⽅法的。因为:锁对象可以是任意对象。

  • wait() 让当前线程处于等待状态,并释放锁

  • notify() 唤醒某个等待中的线程

  • notifyAll() 唤醒所有等待中的线程

  • wait 是Object顶级类的方法,只能在同步方法或者同步块中使用。wait会释放锁,要用notify()唤起,时长大于等于sleep。

  • sleep 是Thread线程类的静态方法,可以在任何地方使用,不会释放锁,它也不需要占用锁。

  • BlockingQueue自带阻塞

三、单线程

同一时刻,只允许执行一个线程

四、多线程

同一时刻可以执行多个线程

  • ⼀个程序运⾏后⾄少有⼀个进程,⼀个进程中可以包含多个线程

  • 并发:指两个或多个事件在同⼀个时间段内发⽣,多任务交替执行。

  • 并⾏:指两个或多个事件在同⼀时刻发⽣(同时发⽣),需要多核cpu。

  • Runnable的实现方式是实现其接口 implements

  • Thread的实现方式是继承其 extends

  • run()方法只是一个类中的普通方法,调用run方法跟调用普通方法一样

  • 而start()方法是启动线程,它创建线程等一系列工作,然后自己调用run里面的任务内容。start0()真正的多线程

五、锁

5.1 synchronized重量级

  1. 同步代码块(性能好)

  2. 同步方法

同一个锁才会有互斥现象
类锁和静态方法锁是同一把锁

1、修饰普通方法(锁住的是当前实例对象)

  • 同一个实例调用会阻塞

  • 不同实例调用不会阻塞

2、同步代码块传参this(锁住的是当前实例对象)

  • 同一个实例调用会阻塞

  • 不同实例调用不会阻塞

3、同步代码块传参变量对象 (锁住的是变量对象)

  • 同一个属性对象才会实现同步

4、同步代码块传参class对象(全局锁)

  • 所有调用该方法的线程都会实现同步

5、修饰静态方法(全局锁)

  • 所有调用该方法的线程都会实现同步

5.2 对象锁(this)和类锁(class)区别?

1、对于静态方法,由于此时对象还未生成,所以只能采用类锁;

2、只要采用类锁,就会拦截所有线程,只能让一个线程访问。

3、对于对象锁(this),如果是同一个实例,就会按顺序访问,但是如果是不同实例,就可以同时访问。

4、如果对象锁跟访问的对象没有关系,那么就会都同时访问

当使用 synchronized 加锁 class 时,无论共享一个对象还是创建多个对象,它们用的都是同一把锁,而使用 synchronized 加锁 this 时,只有同一个对象会使用同一把锁,不同对象之间的锁是不同的。

5.3 Lock(更轻量)

1.lock Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作

2.方法

void lock() 获取锁对象

void unlock() 释放锁对象

5.4 死锁

多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。
由于线程被无限期地阻塞,因此程序不可能正常终止。

线程1
synchronized(obj1){
synchronized(obj2){}
}
线程2
synchronized(obj2){
synchronized(obj1){}
}

六、线程中常用方法

方法名称 方法描述
public fifinal void stop() 终止线程
public void interrupt() 中断线程(只是标记改变中断状态而已,它不会中断一个正在运行的线程。)
public static void yield() 暂停当前正在执行的线程对象,并执行其他线程(礼让)
public fifinal void join() 等待该线程终止(执行当前线程 再执行其它的线程)必须是在开启之后调用

|

Thread.interrupt的作用其实不是中断线程,而是通知线程应该中断了,如果线程处于正常活动状态,线程将继续正常执行,不受影响。

notify方法:

从类 java.lang.Object 继承的方法
用于唤醒在此对象监视器上等待的单个线程。

七、Object****提供的常用的方法

方法名称 方法描述
public fifinal void wait(long timeout) 即时等待
public fifinal void wait() 无限等待
public fifinal void notify() 唤醒在此对象监视器上等待的单个线程(唤醒一个)
public fifinal void notifyAll() 唤醒在此对象监视器上等待的单个线程(唤醒多个)

八、线程第三种创建方式(带返回值)

8.1 步骤

A.定义一个类 实现Callable接口
B.重写call方法
C.FutureTask 实例化任务对象 构建一个Callable接口实现类
D.实例化线程对象 构建FutureTask对象
E.开启线程
F.调用方法 获取返回结果

本文作者:Ritchie

本文链接:https://www.cnblogs.com/wang-zeyu/p/16819773.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Ritchie里其  阅读(64)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
✨欢迎你~🍻
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 遥か Aimer
遥か - Aimer
00:00 / 00:00
An audio error has occurred.

作词 : aimerrhythm/田中ユウスケ

作曲 : 田中ユウスケ

编曲 : 玉井健二/百田留衣

海岸線の雨に ちらばった君の影

思い出が交差する 海辺の街

君はあの日のまま いまも夢を見てた

君はあの日のまま いまも夢を見てた

遥か記憶の空 2人照らす光

遥か記憶の空 2人照らす光

膝までの浅瀬で 見つけた星

君まで届くなんてさ ありえないような

浅い眠りの中で 深い夢から覚めて

浅い眠りの中で 深い夢から覚めて

裸足のまま駆けてく まばゆい星

君はあの日のまま どんな夢を見てた?

君はあの日のまま どんな夢を見てた?

遥か記憶の空 2人照らす光

遥か記憶の空 2人照らす光

いつまでもこうして 笑っててほしい

夜空に舞い上がる 幾千の花びら

でたらめな誓いで 生きてく日々

君から届くなんてさ ありえないような