多线程(2)

线程的生命周期

新建:创建线程对象

就绪:有执行资格,没有执行权

运行:有资格运行,有执行权

​ 阻塞:由一些操作让线程处于改状态。没有执行资格,没有执行权,而通过另一些操作激活它,激活后处于就绪状态。

死亡:线程对象变成垃圾,等待回收

多线程的实现方式二

实现Runnable接口

步骤:

​ 1.自定义类实现Runnable接口

​ 2.重写run()方法

​ 3.创建自定义类的对象

​ 4.创建Theard类对象并把步骤3的对象作为参数传递。

class T1 implements Runnable{

    @Override
public void run() {
for (int i = 0;i < 100;i++){ System.out.println(Thread.currentThread().getName()+":"+i);
}
}
} public class runabletest {
public static void main(String[] args) {
T1 t = new T1(); //public Thread(Runnable target,String name)
Thread t1 = new Thread(t,"线程a");
Thread t2 = new Thread(t,"线程b"); // Thread t1 = new Thread(t);
// Thread t2 = new Thread(t);
// t1.setName("线程1");
// t2.setName("线程2");
t1.start();
t2.start(); }
}

实现接口的好处

1.可以避免由Java单继承带来的局限性。

2.适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码,数据有效的分离,较好的体现了面向对象的思想。

线程安全问题

导致线程安全问题产生原因(也是判断程序是否出现线程安全问题的批准)

1.是否是多线程环境

2.是否有共享数据

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

解决方案

1和2的问题,是不能改变的。所以我们只能考虑改变3

思想:

​ 把多条语句操作共享数据的代码包装成一个整体,让某个线程执行时,其它线程就不能执行。

解决安全问题方案1

同步代码块

格式:synchronized(对象){需要同步的代码块;}

对象是什么:任意对象

需要同步的代码是那部分:多条语句操作共享数据

synchronized (obj) {
while (n > 0) {
try {
Thread.sleep(100);
}catch (Exception e){
System.out.println("线程结束");
}
System.out.println(Thread.currentThread().getName() + "使用" + ":" + (n--));
}
}

注:同步可以解决安全问题的根本原因在对象上。该对象如同锁功能。多个线程必须使用同一把锁。

1.同步代码块的锁对象是任意对象

2.同步方法的格式:把同步关键字synchronized加到方法上

​ 其锁对象是this

public synchronized void show(){
while (n > 0) {
try {
Thread.sleep(100);
}catch (Exception e){
System.out.println("线程结束");
}
System.out.println(Thread.currentThread().getName() + "使用" + ":" + (n--));
}
}

3.静态方法锁对象是类的字节码文件。

同步的特点

前提:多个线程

解决问题时注意:多个对象使用同一把锁。

好处:同步解决了多个线程的安全问题。

弊端:当线程较多时,因为每个线程都会去判断同步的锁,会浪费资源,降低程序运行效率。

如何保证集合是安全的

1.Vector是线程安全的

2.调用Collections中对应的方法

List<String> s = Collections.synchronizedList(new ArrayList<String>());

JDK5以后的Lock

为了直接的表达如何加锁和释放锁,JDK5以后提供了一个新对象Lock

Lock:

​ void lock();获取锁

​ void unlock() ;释放锁

ReentrantLock是Lock的实现类。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; class T3 implements Runnable {
private int n = 100;
Lock l = new ReentrantLock(); @Override
public void run() {
while (true) {
l.lock();
if (n>0)
try {
Thread.sleep(100);
} catch (Exception e) {
System.out.println("线程结束");
}finally {
System.out.println(Thread.currentThread().getName() + "使用" + ":" + (n--));
l.unlock();
}
}
}
} public class Locktest {
public static void main(String[] args) {
T3 t = new T3(); Thread t1 = new Thread(t,"线程a");
Thread t2 = new Thread(t,"线程b");
Thread t3 = new Thread(t,"线程c");
t1.start();
t2.start();
t3.start();
}
}

死锁问题

如果出现同步嵌套,就容易产生死锁问题。

问题描述

指在两个或两个以上的线程在执行过程中,因争夺资源而产生的一种相互等待的现象。

代码

class MyLock{
static Object objA = new Object();
static Object objB = new Object();
} class MyTheard extends Thread{
boolean flag; public MyTheard(boolean flag){
this.flag = flag;
}
public void run(){
if (flag){
synchronized (MyLock.objA){
System.out.println("if objA");
synchronized (MyLock.objB){
System.out.println("if objB");
}
}
}else {
synchronized (MyLock.objB){
System.out.println("else objB");
synchronized (MyLock.objA){
System.out.println("else objA");
}
}
}
} } public class Dielocktest {
public static void main(String[] args) {
MyTheard m1 = new MyTheard(true);
MyTheard m2 = new MyTheard(false); m1.start();
m2.start();
}
}

Javase之多线程(2)的更多相关文章

  1. JavaSE总结--多线程

    进程: 进程之间内存隔离,内存不共享. 线程: 可以共享内存. 每个线程都是一个栈. 多线程的好处: 1)防止程序阻塞. wait与notify的区别: 针对等待队列而言. wait:进入等待队列.必 ...

  2. Javase之多线程(1)

    多线程(1) 多线程的概述 了解多线程之前需要先了解线程,而线程依赖于进程而存在,所以先了解进程. 什么是进程 进程就是正在运行的程序.是系统进行资源分配和调用的独立单位.每一个进程都有它自己的内存空 ...

  3. JavaSE基础---多线程

    进程:正在进行的程序.其实就是一个应用程序运行时的内存分配空间. 线程:进程中一个程序执行控制单元,一条执行路径.进程负责的事应用程序的空间的标识,线程负责的事应用程序的执行顺序. 进程和线程的关系: ...

  4. JAVASE(十七) 多线程:程序、进程、线程与线程的生命周期、死锁、单例、同步锁

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1.程序.进程.线程的理解 1.1 概念 程序(program)是为完成特定任务.用某种语言编写的一组指 ...

  5. 如何自学 Java 开发

    如何自学 Java 开发? 568赞同反对,不会显示你的姓名 李艾米IT路上学习 568 人赞同 Java Web前端技术 HTML 入门视频课程 1 HTML 简介 2 HTML基本结构[ 3 HT ...

  6. 带着新人学springboot的应用09(springboot+异步任务)

    本来想说说检索的,不过不知道什么鬼,下载ElasticSearch太慢了,还是放一下,后面有机会再补上!今天就说个简单的东西,来说说任务. 什么叫做任务呢?其实就是类中实现了一个什么功能的方法.常见的 ...

  7. 数据库之JDBC

    1.简单认识一下JDBC 1).JDBC是什么? java database connection       java数据库连接 作用:就是为了java连接mysql数据库嘛 要详细的,就面向百度编 ...

  8. Android(java)学习笔记215:多线程断点下载的原理(JavaSE实现)

    1. 为什么需要多线程下载?     服务器的资源有限,同时的平均地分配给每个客户端.开启的线程越多抢占的服务的资源就越多,下载的速度就越块. 2. 下载速度的限制条件? (1)你的电脑手机宽带的带宽 ...

  9. Android(java)学习笔记158:多线程断点下载的原理(JavaSE实现)

    1. 为什么需要多线程下载?     服务器的资源有限,同时的平均地分配给每个客户端.开启的线程越多抢占的服务的资源就越多,下载的速度就越块. 2. 下载速度的限制条件? (1)你的电脑手机宽带的带宽 ...

随机推荐

  1. Ubuntu下预览raw格式图片

    默认Ubuntu下资源管理器是不可以直接预览raw格式图片的,这就给查看图片带来很大的不便,下面我们就选择安装UFRaw来预览Raw格式图片 1. 首先在terminal安装UFRaw sudo ap ...

  2. ubuntu18.04 安装 搜狗输入法

    一.安装fcitx sudo apt-get install fcitx-bin 因为搜狗拼音依赖fcitx,相关的依赖库和框架都会自动安装上. sudo apt-get install fcitx- ...

  3. 利用Azure虚拟机安装Dynamics 365 Customer Engagement之八:安装报表扩展及最新更新

    我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...

  4. mysql登陆时出现ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0

    有4到5天没开mysql,这天晚上打=打开phpstudy,想进去mysql练习练习,结果丢给我这个 ERROR 2013 (HY000): Lost connection to MySQL serv ...

  5. SQL Server存储过程数据库日志文件备份的脚本-干货

    还是拿数据库AAAAAAAA为例子        CREATE PROC [dbo].[p_log_backupAAAAAAAA]    @dbname sysname='',             ...

  6. SQL Server 查询某一个数据库存储过程、函数是否包含某一个内容或者脚本

    SELECT obj.Name 名称, sc.TEXT 内容FROM syscomments scINNER JOIN sysobjects obj ON sc.Id = obj.IDWHERE sc ...

  7. 工作日志,证书无效 unable to find valid certification path to requested target

    工作日志,证书无效 unable to find valid certification path to requested target 最近被这个问题弄得头大.导致所有用到 se.transmod ...

  8. Linux系统学习 五、网络基础—网络通信协议

    OSI/ISO七层模型和TCP/IP四层模型 网络层协议和IP划分 OSI的七层框架 物理层:设备之间的比特流的传输.物理接口.电气特性等. 数据链路层:成帧.用MAC地址访问媒介.错误检测与修正. ...

  9. 设计模式-Facade(结构型模式) 针对 最终类的实现通过一系列类的相关操作,重点关注 起始与结尾的操作。

    以下代码来源: 设计模式精解-GoF 23种设计模式解析附C++实现源码 //Facade.h #pragma once class Subsystem1 { public: Subsystem1() ...

  10. docker /var/lib/docker/aufs/mnt 目录满了怎么清理

    1.创建脚本文件 vi cleandocker.sh 内容如下: #!/bin/sh echo "==================== start clean docker contai ...