首页 > 其他分享 >守护线程、锁Synchronized

守护线程、锁Synchronized

时间:2022-10-23 22:11:07浏览次数:39  
标签:Thread Synchronized 对象 void 线程 方法 public 守护

一、守护线程(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() 唤醒在此对象监视器上等待的单个线程(唤醒多个)

标签:Thread,Synchronized,对象,void,线程,方法,public,守护
From: https://www.cnblogs.com/wyzel/p/16819773.html

相关文章

  • 进程和线程
    在我的理解中.进程是一个很大的东西,它占据着自己独有的一片内存空间和各种资源,而线程却很惨.为什么这么说呢,众所周知,进程掌握了大量的资源,就跟老板一样,很有钱,然......
  • 进程与线程的区别
    进程一个进程就是CPU执行的单个任务的过程,是程序在执行过程当中CPU资源分配的最小单位,并且进程都有自己的地址空间,包含了运行态、就绪态、阻塞态、创建态、终止态五个状......
  • 线程和进程的区别?浅显易懂
    进程和线程进程(process)和线程(thread)是操作系统的基本概念,但是它们比较抽象,不容易掌握。最近,我读到一篇材料,发现有一个很好的类比,可以把它们解释地清晰易懂。1.计算机的......
  • 进程和线程的区别
    进程  是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统的基本单位。  是不是觉得根本听不懂?  其实进程我们每天都遇见过,......
  • 进程和线程的区别
    进程一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,一个进程可以有多个线程,比如在Windows系统中,一个运行的xx.exe就是一个进程。 进程的本质:PCB(Proce......
  • 10、CPU 如何选择线程
    在Linux内核中,进程和线程都是用 ​​task_struct​​ 结构体表示的,区别在于线程的task_struct结构体里部分资源是共享了进程已创建的资源,比如内存地址空间、代码段、......
  • 进程与线程的区别
    什么是进程呢?    操作系统为正在运行的程序提供的抽象,就是所谓的进程(process)。一个进程只是一个正在运行的程序。在任何时刻,我们都可以清点它在执行过程中访问或影响......
  • 进程与线程的区别
    进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位)线程:同一类线程共享代码和数据空间,每个线......
  • 线程和进程的区别
     1.进程和线程的概念 进程计算机的核心是CPU,它承担了所有的计算任务;而操作系统是计算机的管理者,它负责任务的调度、资源的分配和管理,统领整个计算机硬件;应用程序侧是具......
  • 1:进程与线程有什么区别?
    1、线程的基本概念概念:线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,......