线程与并发 Thread

基本概念

程序: 一组计算机能识别和执行的指令 ,是静态的代码。

进程: 程序的一次运行活动, 运行中的程序 。

线程: 进程的组成部分,它代表了一条顺序的执行流。

进程线程联系:

① 线程是进程的最小执行和分配单元,不能独立运动,必须依赖于进程。众多的线程组成了进程。

② 资源分配给进程,同一进程的所有线程共享该进程的所有资源。

进程线程区别:

① 调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位

② 并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行

③ 拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源

④ 系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,

导致系统的开销明显大于创建或撤消线程时的开销,所以使用多线程可以减小的资源开销

生命周期

  • 新生状态:

    使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。

  • 就绪状态:

    当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。

  • 运行状态:

    如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。

  • 阻塞状态:

    如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:

    • 等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。

    • 同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。

    • 其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态,

      当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。

  • 死亡状态:

    一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

创建线程的方法

继承Thread类

1.定义继承Thread的子类

2.子类重写Thread的run方法

3.实例化子类对象,创建线程

4.调用start方法,启动线程

源码

public class TestThread {
public static void main(String[] args) {
//创建线程方法1 继承Thread,重写run
NewThread thread = new NewThread();
thread.start();
System.out.println("主线程开始打印数据");
for (int i = 0; i < 5; i++) {
System.out.println("主线程:"+i);
}
}
} class NewThread extends Thread{
@Override
public void run() {
System.out.println("分支线程开始打印数据");
for (int i = 0; i < 5; i++) {
System.out.println("分支线程:"+i);
}
}
}

运行几次程序,发现控制台得到的结果是不一样的。这就是cpu调度的随机性。

实现Runnable接口

1.定义实现Runnable接口的子类

2.子类实现Runnable的run方法

3.通过Thread的类构造器创建线程对象

4.将Runnable实例做为实参传给构造器

5.调用Thread实例的start方法,启动线程

源码

public class TestThread {
public static void main(String[] args) {
//创建线程方法2 实现Runnable接口
Thread thread = new Thread(new NewRunnable());
thread.start();
System.out.println("主线程开始打印数据");
for (int i = 0; i < 5; i++) {
System.out.println("主线程:"+i);
}
}
} class NewRunnable implements Runnable {
@Override
public void run() {
System.out.println("分支线程开始打印数据");
for (int i = 0; i < 5; i++) {
System.out.println("分支线程:"+i);
}
}
}

两种创建方法的区别

  1. 采用实现 Runnable接口的方式创建多线程时,线程类只是实现了 Runnable 接口,还可以继承其他类。(推荐)
  2. 多个线程可以共享同一个Runnable实现类的对象,利于资源同步。
  3. 使用继承 Thread 类的方式创建多线程时,如果需要访问当前线程,直接使用 this 即可获得当前线程。

Thread类

构造方法

常用方法

方法 功能描述
public void start() 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
public void run() 如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
public final void setName(String name) 改变线程名称,使之与参数 name 相同。
public final void setPriority(int priority) 更改线程的优先级。
public final void setDaemon(boolean on) 将该线程标记为守护线程或用户线程。
public final void join(long millisec) 等待该线程终止的时间最长为 millis 毫秒。
public void interrupt() 中断线程。 stop()已过时。
public final boolean isAlive() 测试线程是否处于活动状态。
public final synchronized void join(long millis) 等待该线程终止的时间最长为 millis 毫秒
public static void yield() 线程让步,暂停当前正在执行的线程对象,并执行其他线程。
public static void sleep(long millisec) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。
public static Thread currentThread() 返回对当前正在执行的线程对象的引用。

优先级

 /**  * The minimum priority that a thread can have.  */
public final static int MIN_PRIORITY = 1; /** * The default priority that is assigned to a thread. */
public final static int NORM_PRIORITY = 5; /** * The maximum priority that a thread can have. */
public final static int MAX_PRIORITY = 10;

范围1-10,数字越大系统调用的概率越高。默认优先级为5。

实例测试代码

public class FunctionTest {
public static void main(String[] args) throws InterruptedException {
Thread threadChild = new NewThread();
Thread threadRun = new Thread(new NewRunnable(),"线程2 ");
//先设置优先级
threadChild.setPriority(1);
threadRun.setPriority(10);
//启动线程
threadChild.start();
threadRun.start();
//获取线程属性
threadChild.setName("线程1 ");
System.out.println(threadChild.getName());
System.out.println(threadRun.getName());
System.out.println(Thread.currentThread().getName()); if (threadChild.isAlive())
System.out.println(threadChild.getName()+"活着"); System.out.println("------有人在中间插队------");
threadChild.join();//执行完毕才到下一行
System.out.println("------有人在中间插队------");
//打印线程状态
threadRun.interrupt();
System.out.println(threadChild.isAlive());
System.out.println(threadRun.isAlive()); }
}

后记

以上内容仅仅是很基础的概念认识。

实际应用中会遇到很多问题,比如:

  • 线程同步
  • 线程间通信
  • 线程死锁
  • 线程控制:挂起、停止和恢复

Java基础-线程与并发1的更多相关文章

  1. Java基础-线程安全问题汇总

    Java基础-线程安全问题汇总 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.内存泄漏和内存溢出(out of memory)的区别 1>.什么是内存溢出 答:内存溢出指 ...

  2. Java基础-线程操作共享数据的安全问题

    Java基础-线程操作共享数据的安全问题 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.引发线程安全问题 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运 ...

  3. Java基础——线程总结

    Java基础--线程总结 一.线程是什么? 线程:一个程序里不同的运行路径. 二.怎样创建线程? 两种方法创建线程: 第一种 (1)定义详细功能类实现Runnable接口,能够多次调用而实现数据共享 ...

  4. 《Java基础——线程类》

    Java基础--线程类       一.线程的创建之Thread类: 规则: 通过声明一个新类作为子类继承 Thread 类,并复写 run() 方法,就可以启动新线程并执行自己定义的 run()方法 ...

  5. JAVA基础—线程池

    推荐文章java多线程基础 线程池概述 为什么要使用线程池 1.服务器创建和销毁工作线程的开销很大 2.如果频繁的创建和销毁线程会导致频繁的切换线程,因为一个线程被销毁后,必然要把CPU转让给另一个已 ...

  6. Java基础 - 线程(一)

    一.什么是线程 首先,介绍一下线程.进程的概念. 进程是操作系统分配资源的最小单元,线程是操作系统调度的最小单元.进程是指运行中的应用程序,Windows任务管理器进程窗口看到的每一项都是一个进程.每 ...

  7. java基础—线程(一)

    一.线程的基本概念

  8. 图学java基础篇之并发

    概述 并发处理本身就是编程开发重点之一,同时内容也很繁杂,从底层指令处理到上层应用开发都要涉及,也是最容易出问题的地方.这块知识也是评价一个开发人员水平的重要指标,本人自认为现在也只是学其皮毛,因此本 ...

  9. Java基础--线程创建方式

    线程的创建主要有两种形式,通过继承Thread或者实现Runnable接口,本质上没有太大区别. /** * @date: 2019/7/16 **/ public class ThreadOne i ...

随机推荐

  1. java实现第三届蓝桥杯DNA对比

    DNA对比 脱氧核糖核酸即常说的DNA,是一类带有遗传信息的生物大分子.它由4种主要的脱氧核苷酸(dAMP.dGMP.dCMT和dTMP)通过磷酸二酯键连接而成.这4种核苷酸可以分别记为:A.G.C. ...

  2. Spring源码之自动装配

    我们使用Spring开发过程中经常会用到Autowired注解注入依赖的bean,这部分也是面试的热点问题之一.今天咱们一起来深入研究下自动注入的背后实现原理.首先上一个例子,如下所示: @RestC ...

  3. WPF样式学习第一天

    因为上班的公司要我用wpf写软件,刚毕业出来,学校也没教过wpf,只会winform,再加上wpf用winform的框架写法也能实现很多需求,但是就不能体现wpf的优点了,今天就先来学wpf的样式,因 ...

  4. 源码分析(5)-ArrayList、Vector和LinkedList(JDK1.8)

    一.概述 1.线程安全:ArrayList和LinkedList非线程安全的.Vector线程安全的. 2.底层数据结构:ArrayList和Vector底层数据结构是数组:LinkedList双向链 ...

  5. 痞子衡嵌入式:链接函数到8字节对齐地址或可进一步提升i.MXRT内核执行性能

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT上进一步提升代码执行性能的经验. 今天跟大家聊的这个话题还是跟痞子衡最近这段时间参与的一个基于i.MXRT1170的大项目有 ...

  6. Numpy中数据的常用的保存与读取

    保存到文本文件numpy.savetxt()numpy.loadtxt() import numpy as np x= np.arange(0,10,0.1) np.savetxt('save_x', ...

  7. excel 如何制作带下拉框的动态折线图表

    首先我们需要有个类似下图产品销量的基础数据表. 首先将光标放入表格中任意位置,然后插入一个不带点标记的折线图,然后将折线的颜色设置为灰色. 第一次设置成灰色后,一定善用f4快捷键进行快速的折线颜色设置 ...

  8. Python实现二分法和黄金分割法

    运筹学课上,首先介绍了非线性规划算法中的无约束规划算法.二分法和黄金分割法是属于无约束规划算法的一维搜索法中的代表. 二分法:$$x_{1}^{(k+1)}=\frac{1}{2}(x_{R}^{(k ...

  9. salesforce零基础学习(九十八)Type浅谈

    在Salesforce的世界,凡事皆Metadata. 先通过一句经常使用的代码带入一下: Account accountItem = (Account)JSON.deserialize(accoun ...

  10. C#数据结构与算法系列(八):栈(Stack)

    1.介绍 栈是一个先入后出(FILO-First In Last Out)的有序列表 栈是限制线性表中元素的插入和删除只能在线性表的同一端进行的特殊线性表.允许插入和删除的一端,为变化的一端,称为栈顶 ...