线程与并发 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. 还在用SimpleDateFormat格式化时间?小心经理锤你

    还在用SimpleDateFormat格式化时间?小心经理锤你 场景 本来开开心心的周末时光,线上突然就疯狂报错,以为程序炸了,截停日志,发现是就是类似下述一段错误 java.lang.NumberF ...

  2. 小程序scroll-view实现回到顶部

    一.wxml页面:catchtap阻止冒泡事件. <view class="gotop" hidden='{{!cangotop}}'catchtap="goTop ...

  3. [xDebug] PhpStorm Xdebug远程调试环境搭建

    对于简单的工程,直接print_r();exit()已经足够,但是对于大型项目有时就有点力不从心.. 1,环境介绍 本地:windows10(192.168..)+ phpstorm8远程:Cento ...

  4. [博主推荐]如何利用注册 的 bug 来疯狂注册,不停开小号"做"事情,支持 手机号&邮箱

    [博主推荐]如何利用注册 的 bug 来疯狂注册,不停开小号"做"事情,支持 手机号&邮箱  非常简单 1.手机号注册: 用手机号注册 网站基本都支持 可以用推荐的网址: ...

  5. git新手入门问题总结

    git新手入门问题总结 前言 本人为2019年6月份刚刚毕业,大三暑假中旬来到上海,实习时间大致为十个月,在这十个月里面学到了许多关于git使用方面的知识 经常会逛开源中国水水动态,看看技术帖子学习知 ...

  6. [51nod 1847]奇怪的数学题

    [ 51nod 1847 ]奇怪的数学题 题目   点这里看题目. 分析   是挺奇怪的......   以下定义质数集合为\(P\),\(p_i\)为第\(i\)个质数.   定义\(mp(x)\) ...

  7. flex弹性模型

    flex模型是w3c最新提出的一种盒子模型,很好的解决了普通模型的一些弊端. 一.比较两种盒子模型: demo: 给div添加边框,观察他们的区别 <body> <div class ...

  8. iOS-键盘弹出或隐藏时调整输入框的位置

    要达到自动调整的目标需要监听 keyboardWillShowNotification 跟 keyboardWillHideNotification, 同时需要实现点击其它地方时,通知隐藏键盘的事件 ...

  9. postman发送json数据

    原文链接:https://blog.csdn.net/weixin_33387378/article/details/90721599 1.设置header  Content-Type   appli ...

  10. 记PHP下载大文件失败的一次坑

    说明 php提供文件的储存和下载,nginx作为web服务器,fpm做解析. 现象 当下载一个5M大小的图片时,总提示下载失败,或下载下来的文件不完整,仅显示部分图像(每次下载不一样) php下载相关 ...