前言

本文章部分笔记来自自高诗岩的《java多线程编程核心技术》书。

进程

进程是操作系统结构的基础;是一次程序的执行;是一个程序及其数据在处理机上顺序执行时所发生的活动,是程序在一个数据及上运行的过程,它是系统进行资源分配和调度的一个独立单位。

线程

线程可以理解为在进程中独立运行的子任务,例如,QQ.exe运行时,很多的子任务也在同时运行,如好友视频线程、下载文件线程、传输数据线程、发送表情线程等,这些不同的任务或者说功能都可以同时运行,其中每一项任务完全可以理解成是“线程”在工作,传文件、听音乐、发送图片表情等这些功能都有对应的线程在后台默默地运行。

使用线程

继承Thread

public class MyTread extends Thread{
@Override
public void run(){
super.run();
System.out.println("MYThread");
}
}
public class Main {
public static void main(String[] args) {
MyTread mythreads = new MyTread();
mythreads.start();
System.out.println("结束");
}
}

线程随机性

线程的随机输出是因为CPU将时间片分给不同的线程,线程获得时间片后就执行任务,所以这些线程在交替地执行并输出导致输出结果呈现乱序的现象。

.start()的顺序不代表.run()的顺序

线程.start()的顺序并不代表.run()的顺序,和我们平常代码从上到下顺序执行不太一样。

实现Runnable

我们都知道java支持单继承,使用继承Thread类来开发多线程应用程序在设计上是有局限性的,所以在有些时候,我们可以继承一个类并用implement Runnable接口。

实例共享造成的非线程安全问题

当不共享时,多个线程都是访问各自的实例变量,对各自的变量进行操作, 不让多个线程访问同一个实例变量。
当共享数据时,即多个线程可以访问同一个实例变量。

public class Main {

    public static void main(String[] args) {
MyTread mythreads = new MyTread();
Thread a = new Thread(mythreads,"A");
Thread b = new Thread(mythreads,"B");
Thread c = new Thread(mythreads,"C");
Thread d = new Thread(mythreads,"D");
Thread e = new Thread(mythreads,"E");
a.start();
b.start();
c.start();
d.start();
e.start(); }
}
public class MyTread extends Thread{
private int count =5;
@Override
public void run(){
super.run();
count--;
System.out.println("由"+ currentThread().getName()+"计算,count"+count);
}
}


我们预期希望时可以递减的,结果不应该重复,但是很明显,这样已经出现了所谓的非线程安全问题。

典型场景:5个销售员卖产品,在售出一个产品后,应该在剩余物品上进行减1操作,这个时候就需要对多个线程进行同步的操作。

我们可以在run方法前面加上一个synchronized关键字,这样线程在对这个订单数量减少时就需要排队进行了

线程常用方法:

currentThread() 方法,返回代码段正在被哪个线程调用。

isAlive() 方法,判断当前的线程是否存活。

sleep() 方法,在指定的时间内让当前"正在执行的线程"休眠(暂停执行)

getId()获取线程的唯一标识

判断线程是否为停止状态

1)public static boolean interrupted():测试currentThread()是否已经中断。

2)public boolean this.isInterrupted():测试this关键字所在类的对象是否已经中断。

interrupted():测试当前线程是否已经中断,线程的中断状态由该方法清除。

两个方法的区别:

1)this.interrupted():测试当前线程是否已经是中断状态,执行后具有清除状态标志值为false的功能。

2)this.isInterrupted():测试线程Thread对象是否已经是中断状态,不清除状态标志。

用stop()方法停止线程,即暴力停止线程

利用

stop()方法已经是作废的方法,因为如果暴力性地强制让线程停止,一些请理性工作得不到完成,或者数据添加不完整。

利用stop()释放锁给数据造成不一致的结果

暂停线程suspend()和resume()

使用suspend()方法可以暂停线程,使用resume()方法来恢复线程的执行。

两者的缺点:独占

当使用方法不当,极易造成公共同步对象被独占,其他线程就无法访问公共同步对象的结果。

当一个线程对一个对象的操作一直都没有结束,其他线程就不能访问这个对象,假如这个线程操作这个对象永远进入suspend()状态,其他线程就不能再访问这个对象了。

缺点二:数据不完整

在使用两个方法时容易出现线程暂停,进而导致数据不完整的情况。

yield方法

这个方法是放弃当前的CPU资源,让其他任务去占用CPU执行时间,放弃时间不确定,有可能刚刚放弃,马上又获得CPU时间片。

线程的优先级

线程可以划分优先级,优先级较高的线程得到CPU资源较多,也就是CPU优先执行优先级较高的线程对象中的任务,其实就是让高优先级的线程获得更多的CPU时间片。

通过setPriority()方法设置线程的优先级

在java中,线程的优先级一般分为1~10共10个等级。

线程优先级的继承特性

在Java中,线程的优先级具有继承性

A启动B,A和B的优先级是一样的

优先级的规律性

setPriority()方法设置线程的优先级

一般情况下,高优先级的线程总是大部分先执行完,但是不代表高优先级的线程全部先执行完。

优先级的随机性

优先级较高的线程不一定每一次都先执行完。即:优先级高的线程并不一定每一次都先执行完run()中的任务,线程优先级与输出顺序无关。

守护线程

Java中有两种线程:一种是用户线程,也称非守护线程;另一种是守护线程。

当线程中不存在非守护线程,守护线程自动销毁。典型的守护线程就是垃圾回收机制。当最后的一个用户线程销毁了,守护线程退出,进程随即结束了。

public class Run {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.setDaemon(true);
thread.start();
Thread.sleep(10000);
System.out.println("我离开thread对象也不再打印了,也就是停止了!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class MyThread extends Thread {
private int i = 0; @Override
public void run() {
try {
while (true) {
i++;
System.out.println("i=" + (i));
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

传入setDaemon(true)的线程即为守护线程,所以这里面我们可以看出main是属于用户线程,怎么样可以快速判断出来呢,比如我们将这一行代码注释掉,那么这里在main线程结束后,但是MyThread线程还没有结束,即用户线程还么有结束,这时守护线程就不会终止,所以注释掉后,运行起来这个线程就不会终止了。

对象及变量的并发访问

非线程安全问题会在多个线程对同一个对象中的实例变量进行并发访问时发生,产生的后果就是“脏读”,也就是读取到的数据其实是被更改过的。而线程安全是指获得实例变量的值是经过同步处理的,不会出现脏读的现象。

方法内的变量为线程安全

非线程安全问题存在于实例变量中,对于方法内的私有变量,不存在非线程安全问题

解决方案:

当两个线程同时访问同一个对象的同步方法一定是线程安全的。当线程进入synchronized声明的方法时就会上锁,得等这个方法执行完成后,下一个线程才会进入synchronized声明的方法中。

synchronized方法

调用用关键字synchronized声明的方法一定是排队进行运行的。另外,需要牢牢记住“共享”这两个字,只有共享资源的读写访问才需要同步化,如果不是共享资源,那么就没有同步的必要。

当一线程调用一个对象的synchronized类型方法时,其他线程可以调用该对象的的非synchronized方法。

当在一个方法添加synchronized并不是锁方法,而是锁当前的类的对象。在Java中,“锁”就是对象,“对象”可以映射成“锁”,哪个线程拿到这把锁,哪个线程就可以执行这个对象的synchronized同步方法。

synchronized拥有重入锁的功能,当一个线程得到一个对象的锁后,再次请求此对象锁时可

以得到该对象锁的,意思就是当我们在一个synchronized方法内调用其他方法块时,是可以得到锁的。

“可重入锁”是指自己还可以获取自己的内部锁。

synchronized方法和synchronized(this)代码块都是锁定当前对象

总结

简单的一个学习笔记,记录一下。

java线程的创建的更多相关文章

  1. Java线程:创建与启动

    Java线程:创建与启动 一.定义线程   1.扩展java.lang.Thread类.   此类中有个run()方法,应该注意其用法: public void run() 如果该线程是使用独立的 R ...

  2. 漫谈并发编程(二):java线程的创建与基本控制

    java线程的创建 定义任务           在java中使用任务这个名词来表示一个线程控制流的代码段,用Runnable接口来标记一个任务,该接口的run方法为线程运行的代码段. public ...

  3. JAVA - 线程从创建到死亡的几种状态都有哪些?

    JAVA - 线程从创建到死亡的几种状态都有哪些? 新建( new ):新创建了一个线程对象. 可运行( runnable ):线程对象创建后,其他线程(比如 main 线程)调用了该对象 的 sta ...

  4. Java线程之创建线程

    翻译自:https://www.journaldev.com/1016/java-thread-example 进程 进程是一个自包含的执行环境,它可以被看成一个程序或应用程序.然而一个应用程序本身包 ...

  5. 【JAVA并发第二篇】Java线程的创建与运行,线程状态与常用方法

    1.线程的创建与运行 (1).继承或直接使用Thread类 继承Thread类创建线程: /** * 主类 */ public class ThreadTest { public static voi ...

  6. Java线程的创建及启动

    1.继承Thread类,重写该类的run()方法. package samTest; import java.util.Scanner; /** * Created by Sam on 2018-01 ...

  7. Java 线程的创建和启动

    Java 使用 Thread 类代表线程,所有的线程对象都必须是 Thread 类或其子类的实例.每个线程的作用是完成一定的任务,实际上就是执行一段程序流(一段顺序执行的代码). Java 使用线程执 ...

  8. Java线程的创建方式三:Callable(四)

    一.Java实现多线程的三种方式 方式一:继承Thread类: public class Test extends Thread { public static void main(String[] ...

  9. java线程之创建线程类

    1.extends Thread方法 class Person extends Thread { int sum1 = 50; // 含参构造器 public Person(String name) ...

  10. ThreadPoolExecutor – Java Thread Pool Example(java线程池创建和使用)

    Java thread pool manages the pool of worker threads, it contains a queue that keeps tasks waiting to ...

随机推荐

  1. CentOS基本命令手册

    一.磁盘使用情况 两个命令df .du结合比较直观 df -h #查看整台服务器的硬盘使用情况 du -sh * #查看每个文件夹的大小 二.tar 用法 压缩 tar tar -czvf test. ...

  2. 关于安装Wind金融终端后,启动QT后频繁跳出WDF.dll文件注册成功窗口的问题

    安装Wind金融终端后,启动QT后频繁跳出WDF.dll文件注册成功窗口的信息. 经过排查后发现,主要问题出在系统环境变量上. 安装了wind金融终端后,用户系统环境变量PATH里多了两个wind相关 ...

  3. 子接口vlan终结

    问题: 在华为的NE40E设备上,配置三层字接口的ip后,接口的physical状态为up, protocol为down,接口还是不可用. 解决方案: 需要在子接口上配置vlan终结,配置如下: 为什 ...

  4. win10下Word点击链接跳转,提示“由于本机的限制,该操作已取消”

    Word按住Ctrl点击链接进行跳转,提示"由于本机的限制,该操作已取消,请联系管理员" 网上很多,修改注册表 这边要说的是,修改重启word ,还不行的解决方法:点开任务管理器- ...

  5. 在Mac上不常用但会用到的命令

    文章目录 1. chflags 2. rename 1. chflags chflags hidden filename 给文件添加隐藏属性 chflags nohidden filename 去掉文 ...

  6. linux服务器已知目录下根据特定字符串查找文件

    很久不用的一个项目的测试环境迁移后,启动项目时,发现日志一直报错,在opt/下缺少一个jar包,思路是:查看配置文件,想找到具体是哪个配置文件写了需要用到这个jar包,然后修改到正确路径下重新启动尝试 ...

  7. Spring Cloud 学习笔记(周阳)

    参考博客:https://blog.csdn.net/u011863024/article/details/114298270 内容:netflix,alibaba

  8. 红黑树(map与unorder_map)B B+树

    红黑树(map) 这个里面有插入的几种方式:红黑树性质的理解 先说性质,1 每个节点要么红要么黑,2 一个节点为红色,左右两个孩子都是黑, 3 根节点是黑, 4 每个叶子(nil)节点都是黑色, 5 ...

  9. 基于声网 Flat 构建白板插件应用“成语解谜”的最佳实践

    前言 本文作者赵杭天.他参加了"2022 RTE 编程挑战赛"--"赛道二 场景化白板插件应用开发" , 并凭借作品"成语解谜"获得了该赛道 ...

  10. springboot--yaml数据读取的三种方式

    结果: