1 线程控制

t.join():让主线程进入线程池,等待t执行完才执行。

t.sleep():让线程阻塞,休眠一段时间,休眠结束后进入就绪状态。不会释放锁。

t.yield():让线程让出CPU,从运行态进入就绪态。可能会接着进入运行态。

t.setDaemon():设置为守护线程,非守护线程都死了的时候自动终止。

2 线程的分类

线程分为:守护线程 用户线程

  • 守护线程和用户线程基本上是相同的,唯一区别就是判断JVM何时离开

  • 守护线程是用来服务用户线程的。通过在start方法之前调用thread.setDaemon(true) 可以将一个用户线程变成守护线程

  • java的垃圾回收 他是一个典型的守护线程

  • 如果JVM中都是守护线程,JVM将退出(用户线程执行结束 守护线程无论是否结束 都将终止执行)

3 线程的生命周期

jdk中用Thread State定义了线程的状态:

  • 线程状态。线程可以处于以下状态之一:

    • NEW 尚未启动的线程处于此状态。

    • RUNNABLE 在Java虚拟机中执行的线程处于此状态。

    • BLOCKED 被阻塞等待监视器锁定的线程处于此状态。

    • WAITING 正在等待另一个线程执行特定动作的线程处于此状态。

    • TIMED_WAITING 正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。

    • TERMINATED 已退出的线程处于此状态。

    线程的状态通常分为5种状态:

    新建:当一个Thread类及其子类的对象被声明并创建时,此时的线程对象就处于新建状态

    就绪 : 处于新建状态的线程被start后,线程将进入CPU的执行队列等待获得CPU的执行权,此时的线程已经具备了运行的条件,只是还有获得CPU的执行权

    运行:当就绪的线程获得CPU的执行权 ,处于运行状态

    阻塞:在某种特殊的情况下,被人为挂起或执行输入输出操作时,让出CPU并临时中止自己的执行。此时线程就进入阻塞状态

    死亡:线程完成了他的全部工作或被线程被提前强制性的终止 或出现异常导致线程异常结束。

    线程状态之间的相互转换

一个线程一旦死亡 是不可以在重新启动的。

4.线程同步

public class SellTicketDemo {
public static void main(String[] args) {
SellTicket st = new SellTicket();
//创建三个线程
Thread t1 = new Thread(st,"1号窗口");
Thread t2 = new Thread(st,"2号窗口");
Thread t3 = new Thread(st,"3号窗口");
//启动线程
t1.start();
t2.start();
t3.start();

}
}
public class SellTicket implements Runnable{
private int ticktes = 100;
@Override
public void run() {
while(true){
if(ticktes > 0 ){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第" + ticktes+"张票");//会出现数据不同步的现象,与实际需求不符
ticktes--;
}
}
}
}

4.1 解决数据安全问题--同步代码块

出现问题的条件:

1 多线程环境

2 有共享数据

3 有多条语句操作共享数据

如何解决线程安全问题:

基本的思想:让程序没有安全问题的环境

怎么实现呢? 把多条语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行。

java提供了解决的方式是使用同步代码块或同步方法:synchronized 相当于给代码加锁

可以用在代码块和方法上 分别称为同步代码块和同步方法:

代码块:synchronized(obj/this){

共享代码;

}

在同步代码块中 谁来担当这个所对象呢?

任意对象都可以充当所对象 一般情况下使用this

4.2 解决数据安全问题--同步方法

在方法的声明上添加synchronized关键字

同步成员方法

静态同步方法:static synchronized

静态方法的同步代码块:使用类名.class作为锁对象

静态的同步方法或者静态方法中的同步代码块的所对象是类名.class对象

单例设计模式的懒汉式的线程安全问题

public class Singleton {
private static Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
if( instance == null){
synchronized (Singleton.class){
if(instance ==null){
instance = new Singleton();
}
}
}
return instance;
}
}

4.6 线程安全的类

StringBuffer 线程安全的可变字符序列

StringBuilder 线程不安全的可变字符序列

Vector 线程同步的

HashTable 线程同步的 是一个哈希表的实现

在实际使用时,如果不需要线程安全的实现,推荐使用与之功能相同的 但是线程不同步的实现

5 线程的死锁的演示

死锁是我们需要规避的问题

不同的线程分别占用对方所需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就行成了线程死锁

出现死锁 不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态 无法继续

死锁问题的出现是一个概率时间。

死锁问题的解决:

1 减少同步代码块或同步方法的嵌套

2 尽量减少同步资源的定义

3 使用专门的算法

提示:

1 明确那些代码是多线程运行的代码,就是需要写入run方法

2 明确那些数据是共享数据

3 明确多下称运行代码中的那些语句操作了共享数据

6 线程通信

6.1 什么时候需要线程通信

多个线程并发执行,在默认情况下CPU随机切换线程,如果我们希望他们有规律的执行,就需要使用线程通信。

6.2 线程间如何通信

如果线程需要等待 就调用的wait().wait()方法可以等待时间结束或者被唤醒。如果要唤醒一个等待的线程 那么就使用notify() /notifyAll()

6.3 互斥锁

互斥锁 依次最多只能有一个线程持有锁

锁是用于通过多个线程控制对共享资源的访问的工具。 通常,锁提供对共享资源的独占访问:一次只能有一个线程可以获取锁,并且对共享资源的所有访问都要求首先获取锁

lock.lock():加锁 lock.unlock()解锁

Interface Lock 可以使用的实现类 ReentrantLock

  • 一个可重入互斥Lock具有与使用synchronized方法和语句访问的隐式监视锁相同的基本行为和语义,但具有扩展功能。

Condition

c1.await():使当前线程等待,直到c1.singal()或者interrupt()打断阻塞状态,或者到await()指定的时间。

c1.signal():唤醒一个等待线程

c1.signalAll():唤醒所有等待进程

不同的线程需要使用不同的 Condition 这样就能区分唤醒额时候唤醒的是那个线程

public class ThreadLock {
public static void main(String[] args) {
ThreadLock tw = new ThreadLock();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
tw.print1();
}

}
}).start();
new Thread(){
@Override
public void run() {
while(true){
tw.print2() ;
}
}
}.start();
new Thread(){
@Override
public void run() {
while(true){
tw.print3() ;
}
}
}.start();
}
// 创建Lock锁对象
Lock lock = new ReentrantLock();
//创建锁使用的条件
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Condition c3 = lock.newCondition();
// 创建一个唤醒标志
int flag = 1;
public void print1(){
lock.lock();//给当前代码上锁
if(flag != 1){
try {
c1.await();//当前线程处于等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print("中");
System.out.print("北");
System.out.print("大");
System.out.print("学");
System.out.println();
flag = 2;
c2.signal();//唤醒c2
lock.unlock();//释放锁
}
public void print2(){
lock.lock();
if(flag != 2){
try {
c2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print("塔");
System.out.print("里");
System.out.print("木");
System.out.print("大");
System.out.print("学");
System.out.println();
flag =3;
c3.signal();
lock.unlock();
}
public void print3(){
lock.lock();
if(flag != 3){
try {
c3.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print("青");
System.out.print("岛");
System.out.print("大");
System.out.print("学");
System.out.println();
flag =1;
c1.signal();
lock.unlock();
}
}

6.4生产者—消费者模型

生产者消费者模型的作用是什么?

1通过平衡生产者的生产能力和消费者消费能力来提升整个系统的运行效率

2 解耦

多线程的学习重点:

1 线程的创建方式

2线程的生命周期(线程的五种状态的转换)

3 线程同步

4 线程通信

15Java进阶 进程的更多相关文章

  1. Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型

    Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型 一丶互斥锁 含义: ​ ​ ​ 每个对象都对应于一个可称为" 互斥锁&qu ...

  2. Python进阶----进程间数据隔离, join阻塞等待, 进程属性, 僵尸进程和孤儿进程, 守护进程

    Python进阶----进程间数据隔离, join阻塞等待, 进程属性, 僵尸进程和孤儿进程, 守护进程 一丶获取进程以及父进程的pid 含义:    进程在内存中开启多个,操作系统如何区分这些进程, ...

  3. python进阶------进程线程(五)

    Python中的IO模型 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别 ...

  4. python进阶------进程线程(四)

    Python中的协程 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其 ...

  5. python进阶------进程线程(三)

    python中的进程 1.multiprocessing模块 由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进 ...

  6. python进阶-------进程线程(二)

    Python中的进程线程(二) 一.python中的"锁" 1.GIL锁(全局解释锁) 含义: Python中的线程是操作系统的原生线程,Python虚拟机使用一个全局解释器锁(G ...

  7. python进阶------进程线程(一)

    Python中的进程线程 一.进程线程的概念 1.1进程: 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及 ...

  8. python进阶——进程/线程/协程

    1 python线程 python中Threading模块用于提供线程相关的操作,线程是应用程序中执行的最小单元. #!/usr/bin/env python # -*- coding:utf-8 - ...

  9. Java进阶(四十三)线程与进程的区别

    Java进阶(四十三)线程与进程的区别 1.线程的基本概念   概念:线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必 ...

随机推荐

  1. 面试热点|理解TCP/IP传输层拥塞控制算法

    0x00.前言 通过本文你将了解到以下内容: 拥塞控制概念以及其背景 流量控制和拥塞控制的区别与联系 拥塞控制主要过程详解 伙伴们认真学习一下,让offer来得更猛烈些吧! 0x01.TCP/IP协议 ...

  2. 题解 P3940 分组

    有些梦想虽然遥不可及,但不是不可能实现.只要我足够的强. 前言 调了挺长时间的,并查集合并的时候需要 find 一下,不然会炸内存.... 解题思路 参考了题解区一篇思路非常好的题解,在这里讲一下自己 ...

  3. Serverless Web Function 实践教程(一):快速部署 Node.js Web 服务

    作为目前广受欢迎的 Web 服务开发语言,Node.js 提供了众多支持 HTTP 场景的相关功能,可以说是为 Web 构建而生.因此,基于 Node.js,也诞生了多种 Web 服务框架,它们对 N ...

  4. .NET Core/.NET5/.NET6 开源项目汇总5:权限管理系统项目

    系列目录     [已更新最新开发文章,点击查看详细] 企业管理系统一般包含后台管理UI.组织机构管理.权限管理.日志.数据访问.表单.工作流等常用必备功能.下面收集的几款优秀开源的管理系统,值得大家 ...

  5. 手写Spring,定义标记类型Aware接口,实现感知容器对象

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 同事写的代码,我竟丝毫看不懂! 大佬的代码,就像 "赖蛤蟆泡青蛙,张的丑玩 ...

  6. Linux中mail的用法

    简介:mail命令是命令行的电子邮件发送和接收工具.操作的界面不像elm或pine那么容易使用,但功能非常完整Red Hat上sendmail服务一般是自动启动的.可以通过下面的命令查看sendmai ...

  7. 42、sort命令

    排序和把相同的放到一起: 42.1.sort命令介绍: sort命令是一个排序介绍,简而言之就是以什么为分割符,对第几列进行什么排序操作: 42.2.sort命令参数介绍: -u #去重,会直接把重复 ...

  8. 《TCP/IP详解 卷1:协议》第4章 ARP:地址解析协议

    4.1 引言 本章我们要讨论的问题是只对TCP/IP协议簇有意义的IP地址.数据链路如以太网或令牌环网都有自己的寻址机制(常常为48 bit地址),这是使用数据链路的任何网络层都必须遵从的.一个网络如 ...

  9. buu firmware

    一.路由器固件,给的是bin文件,要用binwalk将固件文件系统提取出来,同时binwalk的版本要完整不然解压不了文件,下面说的很清楚了. https://blog.csdn.net/QQ1084 ...

  10. WPF教程八:如何更好的使用Application程序集资源

    这一篇单独拿出来分析这个程序集资源,为的就是不想让大家把程序集资源和exe程序强关联,因为程序集资源实际上是二进制资源,后续编译过程中会被嵌入到程序集中,而为了更方便的使用资源,我们要好好梳理一下程序 ...