按照规划,从本篇开始我们开启『并发』系列内容的总结,从本篇的线程开始,到线程池,到几种并发集合源码的分析,我们一点点来,希望你也有耐心,因为并发这块知识是你职业生涯始终绕不过的坎,任何一个项目都或多或少的要涉及一些并发的处理。

这一系列文章只能算是对并发这块基本理论知识的一个总结与介绍,想要成为并发高手,必然是需要通过大规模并发访问的线上场景应用,或许以后我有了相关经验了,再给你们做一点分享吧。

基本的进程线程概念

进程和线程算是操作系统内两个很基本、很重要的概念了,进程是操作系统中进行保护和资源分配的基本单位,操作系统分配资源以进程为基本单位。而线程是进程的组成部分,它代表了一条顺序的执行流。

系统中的进程线程模型是这样的:

进程从操作系统获得基本的内存空间,所有的线程共享着进程的内存地址空间。当然,每个线程也会拥有自己私有的内存地址范围,其他线程不能访问。

由于所有的线程共享进程的内存地址空间,所以线程间的通信就容易的多,通过共享进程级全局变量即可实现。

同时,在没有引入多线程概念之前,所谓的『并发』是发生在进程之间的,每一次的进程上下文切换都将导致系统调度算法的运行,以及各种 CPU 上下文的信息保存,非常耗时。而线程级并发没有系统调度这一步骤,进程分配到 CPU 使用时间,并给其内部的各个线程使用。

在分时系统中,进程中的每个线程都拥有一个时间片,时间片结束时保存 CPU 及寄存器中的线程上下文并交出 CPU,完成一次线程间切换。当然,当进程的 CPU 时间使用结束时,所有的线程必然被阻塞。

JAVA 对线程概念的抽象

JAVA API 中用 Thread 这个类抽象化描述线程,线程有几种状态:

NEW:线程刚被创建

RUNNABLE:线程处于可执行状态

BLOCKED、WAITING:线程被阻塞,具体区别后面说

TERMINATED:线程执行结束,被终止

其中 RUNNABLE 表示的是线程可执行,但不代表线程一定在获取 CPU 执行中,可能由于时间片使用结束而等待系统的重新调度。BLOCKED、WAITING 都是由于线程执行过程中缺少某些条件而暂时阻塞,一旦它们等待的条件满足时,它们将回到 RUNNABLE 状态重新竞争 CPU。

此外,Thread 类中还有一些属性用于描述一个线程对象:

private long tid:线程的序号

private volatile char name[]:线程的名称

private int priority:线程的优先级

private boolean daemon = false:是否是守护线程

private Runnable target:该线程需要执行的方法

其中,tid 是一个自增的字段,每创建一个新线程,这个 id 都会自增一。优先级取值范围,从一到十,数值越大,优先级越高,默认值为五。

线程案例:

packagedemo.knowledgepoints.scheduledtask.run;/***

* 线程类*/

public class ThreadTest implementsRunnable {public static int ticket = 9;

@Overridepublic voidrun() {try{

System.out.println("当前线程:"+Thread.currentThread().getName());while(true){synchronized (this) {

Thread.sleep(1000L);if (this.ticket > 0) {

ticket--;

System.out.println(Thread.currentThread().getName()+ ":出售一张票!");

System.out.println("剩余票量:" +ticket);

}else{

System.out.println("没有票了!");

}

}

}

}catch(Exception e) {

e.printStackTrace();

}

}

}

packagedemo.knowledgepoints.scheduledtask.run;public classThreadMemo {public static voidmain(String[] args) {

ThreadTest threadTest1=newThreadTest();newThread(threadTest1).start();newThread(threadTest1).start();

}

}

运行结果

从案例中我们可以知道:ThreadTest  继承了 Runnable 接口,并且实现了run方法。

在 ThreadMemo 中,我们创建ThreadTest,并且是执行了start() 方法,并没有直接执行run方法。

从运行结果我们可以看出:我们运行了run方法里面的程序。

并且线程1和线程0 交替执行。

下面我们来看看这个线程的执行过程。

Runnable 是一个接口,它抽象化了一个线程的执行流,定义如下:

@FunctionalInterfacepublic interfaceRunnable {/*** When an object implementing interface Runnable is used

* to create a thread, starting the thread causes the object's

* run method to be called in that separately executing

* thread.

*

* The general contract of the method run is that it may

* take any action whatsoever.

*

*@seejava.lang.Thread#run()*/

public abstract voidrun();

}

第一步:实现接口Runnable接口。

第二步:创建一个线程,并且将实现Runnable接口的类放进去。

第三步:使用线程的start() 方法,启动线程。这个时候,Jvm会自动去找到run方法,并且执行run方法,同时不影响主进程继续往下执行。

线程案例:

public class Thread1 extendsThread {public static int ticket = 5;

@Overridepublic voidrun() {try{

System.out.println("当前线程:"+Thread.currentThread().getName());while(true){synchronized (this) {

Thread.sleep(2000L);if (this.ticket > 0) {

ticket--;

System.out.println(Thread.currentThread().getName()+ ":出售一张票!"+"剩余票量:" +ticket);

}else{

System.out.println("没有票了!");

}

}

}

}catch(Exception e) {

e.printStackTrace();

}

}

}

public classThreadTest1 {public static voidmain(String[] args) {

Thread thread= newThread1();

thread.start();

System.out.println("主线程!");

}

}

运行结果:

这是第二种线程实现方式:继承 Thread 类。

看Thread 类:

class Thread implements Runnable

其实就是实现了Runnable 接口。

列举一下:Thread 方法。

1、sleep

public static native void sleep(long millis)

这是一个本地方法,用于阻塞当前线程指定毫秒时长。

2、start

public synchronized void start()

这个方法可能很多人会疑惑,为什么我通过重写 Runnable 的 run 方法指定了线程的工作,但却是通过 start 方法来启动线程的?

那是因为,启动一个线程不仅仅是给定一个指令开始入口即可,操作系统还需要在进程的共享内存空间中划分一部分作为线程的私有资源,创建程序计数器,栈等资源,最终才会去调用 run 方法。

3、interrupt

public void interrupt()

这个方法用于中断当前线程,当然线程的不同状态应对中断的方式也是不同的,这一点我们后面再说。

4、join

public final synchronized void join(long millis)

这个方法一般在其他线程中进行调用,指明当前线程需要阻塞在当前位置,等待目标线程所有指令全部执行完毕。

线程案例:

public class ThreadDemo1 implements Callable{

@Overridepublic String call() throwsException {return "你好";

}public static void main(String[] args) throwsExecutionException, InterruptedException {

FutureTask futureTask= new FutureTask(newThreadDemo1()) ;newThread(futureTask).start();

System.out.println(futureTask.get());

}

}

运行结果:

java线程概念_《Java基础知识》Java线程的概念相关推荐

  1. java的技术定义_java基础知识——Java的定义,特点和技术平台

    (作者声明:对于Java编程语言,很多人只知道怎么用,却对其了解甚少.我也是其中一员.所以菜鸟的我,去查询了教科书以及大神的总结,主要参考了<Java核心技术>这本神作.现在分享给大家!) ...

  2. 零基础自学java的难处_零基础自学Java 在学习中要注意哪些问题

    如果是零基础自学Java编程,在学习过程中有很多要注意的问题,想要学好学精必然是件难事,并且可能会走弯路浪费很多时间,短时间内是不可能学成参加工作的,想要成为专业的Java程序员并不容易,技术过硬尤为 ...

  3. 学java 的要点_零基础学Java,掌握Java的基础要点

    对于程序员群体来说,了解一定的技巧会对学习专业技能更有帮助,也更有助于在自己的职业发展中处于有利地位,无限互联Java培训专家今天就为大家总结Java程序员入门时需要掌握的基础要点: 掌握静态方法和属 ...

  4. java 百度爬虫_零基础写Java知乎爬虫之先拿百度首页练练手

    上一集中我们说到需要用Java来制作一个知乎爬虫,那么这一次,我们就来研究一下如何使用代码获取到网页的内容. 首先,没有HTML和CSS和JS和AJAX经验的建议先去W3C(点我点我)小小的了解一下. ...

  5. java第二章_零基础学Java第二章

    一.第一个代码案例 1.1. HelloWorld案例 1.1.1 代码执行流程 我们写的代码都将以.java开头的文件保存,经过类编译器编译成.class的字节码文件,然后通过解释器翻译与机器交流 ...

  6. java学习出师_零基础学java来这里 出师如此简单

    当今时代是互联网的时代,互联网时代的到来,使得我们的生活更加便利,同时互联网时代的到来也大大增加了市场对于技术人才的需求,在此时,Java编程语言的许多特性势使得它迅速成长,学习的人也越来越多 jav ...

  7. java线程堆栈_深入JVM剖析Java的线程堆栈

    在这篇文章里我将教会你如何分析JVM的线程堆栈以及如何从堆栈信息中找出问题的根因.在我看来线程堆栈分析技术是Java EE产品支持工程师所必须掌握的一门技术.在线程堆栈中存储的信息,通常远超出你的想象 ...

  8. Java中易忽略的基础知识

    欢迎关注我的公众号[软件大爆炸] Java学习中的碎碎念 Java中易忽略的基础知识 Java面向对象基础 Java中的核心类 Java抽象类和接口 Java中的异常 Java中的泛型与集合 Java ...

  9. java基础知识(java基础知识刷题软件)

    自学Java 怎么入门 在学习Java前,你有必要思考一下: 你对学习Java是否有兴趣2.您是否能静下心学习Java 大家都知道兴趣很重要,如果您对Java没有兴趣,相信你没法能静下心学习Java ...

  10. JAVA面试题之JVM基础知识

    JAVA面试题总结-JVM的基础知识 JAVA面试题之JVM基础知识 说一下JVM的主要组成部分及作用 说一下 jvm 运行时数据区? 说一下堆和栈的区别? 队列和栈是什么?有什么区别? 什么是双亲委 ...

最新文章

  1. 前端开发神器之ngrok
  2. Python学习——反射
  3. Linux查看谁修改的文件,linux如何查看近来修改的文件
  4. Codis安装与部署
  5. 动态执行shell脚本
  6. 会“聆听”用户,用户反馈设计
  7. php 连接 onenet,arduino一直连接不上onenet
  8. 【408考研笔记】操作系统完整知识点
  9. 明翰英语教学系列之雅思听力篇V0.2(持续更新)
  10. 前端开发中PC端和移动端网站的区别
  11. 用递归法求两个数的最大公约数
  12. 电流互感器的一些计算
  13. redis cluster 4.0.9 之四: redis-trib.rb add-node
  14. 单片机转向灯c语言编程,单片机汇编语言编程:汽车转向灯控制器
  15. 直通大厂web入门级网页快速开发(建议收藏)
  16. 毫秒和微秒分别和秒怎么换算?
  17. 艾永亮超级产品:企业管理者对企业发展起到什么作用?
  18. 关于实现局域网内视频播放
  19. 求secx和cscx的不定积分
  20. Linux开发(十三):守护进程

热门文章

  1. 我和linux的第四天
  2. 蚂蚁的难题(一) http://acm.nyist.net/JudgeOnline/status.php?pid=744
  3. 学习笔记之Fluent Python
  4. mysql 优化语句
  5. WPF的Clipboard.SetText()有问题
  6. My1stServlet
  7. Docker容器学习梳理--日常操作总结
  8. C++基础与面向对象
  9. CF Theatre Square
  10. [bug]超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。...