多线程编程学习一(Java多线程的基础).
一、进程和线程的概念
进程:一次程序的执行称为一个进程,每个 进程有独立的代码和数据空间,进程间切换的开销比较大,一个进程包含1—n个线程。进程是资源分享的最小单位。
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小,线程是CPU调度的最小单位。
多进程:指操作系统能同时运行多个任务(程序)。
多线程:指同一个程序中有多个顺序流在执行,线程是进程内部单一控制序列流。

二、多线程的优势
单线程的特点就是排队执行,也就是同步。而多线程能最大限度的利用CPU的空闲时间来处理其他的任务,系统的运行效率大大提升,使用多线程也就是在执行异步。
三、使用多线程
实现多线程编程的方式主要有两种,一种是继承Thread类,另一种是实现Runable接口。其实,使用继承Thread类的方式创建新线程时,最大的局限就是不支持多继承,因为Java语言的特点就是单根继承,所以为了支持多继承,完全可以实现Runnable接口,一边实现一边继承。但是这两种方式创建的线程在工作时的性质是一样的,没有本质的差别。
public class Thread1 extends Thread {
private int count=5;
@Override
public void run()
{
for (int i=0;i<2;i++){
System.out.println("现在是线程"+currentThread().getName()+"在执行:"+count--); }
}
}
public class Thread2 implements Runnable {
private int count=5;
@Override
public void run() {
for(int i=0;i<2;i++){
System.out.println("现在是线程"+Thread.currentThread().getName()+"在执行:"+count--); }
}
}
public class Test{
public static void main(String[] args){
//集成Thread类
Thread1 thread1=new Thread1();
Thread t1=new Thread(thread1,"A");
Thread t2=new Thread(thread1,"B");
Thread t3=new Thread(thread1,"C");
t1.start();
t2.start();
t3.start();
//实现Runable接口
Thread2 thread2=new Thread2();
Thread t4=new Thread(thread2,"A2");
Thread t5=new Thread(thread2,"B2");
Thread t6=new Thread(thread2,"C2");
t4.start();
t5.start();
t6.start();
}}

演示这个结果是为了说明以下两点:
1、CPU对线程的调度具有不确定性,采用“抢占式”调度。
2、对于网上经常说的,实现 Runnable 接口的线程可以实现共享数据,而继承 Thread 的线程就不能。其实不然,它们两者的区别仅是单继承的限制以及一些用法的不同(比如 如果你想对这个Thread对象做点别的事情(比如getName),那么你就必须通过调用Thread.currentThread()方法得到对此线程的引用),没有实质的差别。
四、synchronized 关键字
多线程的锁机制,通过在多线程要调用的方法前加入synchronized 关键字,使多个线程在执行方法时,要首先尝试去拿这把锁,如果能够拿到这把锁,那么这个线程就可以执行synchronize里面的代码。如果不能拿到这把锁,那么这个线程就会不断地尝试拿这把锁,直到拿到这把锁。synchronized 可以在任意对象及方法上加锁,而加锁的这段代码称为“互斥区” 或 “临界区”。
使用synchronized关键字主要是为了保证当前线程在执行过程中,不被其他线程抢占并修改了共享的资源,从而导致线程不安全的情况出现。

五、常用线程方法
1、Thread.currentThread()方法:返回代码段正在被哪个线程调用的信息。最常见的就是Thread.currentThread().getName()。
2、isAlive()方法:判断当前的线程是否处于活动状态。什么是活动状态呢?活动状态就是线程已经启动且尚未终止。线程正在运行或准备开始运行的状态,就认为线程是“存活”的。
3、Thread.sleep()方法:在指定的毫秒数内让"正在执行的线程"休眠(暂停执行)。这个“正在执行的线程”是指this.currentThread()返回的线程。
4、getId()方法:取得该线程的唯一标识。
5、Thread.interrupt()方法:用于中断线程,这里需要注意Thread.interrupt 的作用其实也不是中断线程,而是「通知线程应该中断了」,具体到底中断还是继续运行,应该由被通知的线程自己处理。具体来说,当对一个线程,调用 interrupt() 时,
① 如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常,并且清除中断标志,使之变为false。
② 如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true,仅此而已。被设置中断标志的线程将继续正常运行,不受影响。
Thread thread = new Thread(() -> {
// 通过这样来检查这个中断标志位是否设置为 true 来判断是否进行程序逻辑,不要使用废弃的 Thread.stop, Thread.suspend, Thread.resume
while (!Thread.interrupted()) {
// do more work.
}
});
thread.start();
// 一段时间以后
thread.interrupt();
值得一提的是,判断线程是否中断有两个办法:
- interrupted():测试当前线程是否已经是中断状态,执行后具有将状态标志清除的false的功能。(这里需要特别注意的是即使是MyThread.interrupted(),测试的仍然是当前线程(this.currentThread())的状态)。
- isInterrupted():测试线程Thread对象是否已经是中断状态,但不清除状态标志。
通过抛出异常来中断线程:
public class MyThread extends Thread {
@Override
public void run(){
try {
for (int i = 0; i < 500000; i++) {
if (this.interrupted()) {
System.out.println("已经是停止状态了!我要退出了");
throw new InterruptedException();
}
System.out.println("i=" + (i + 1));
}
} catch (InterruptedException e) {
System.out.println("进入MyThread.java类run方法中的catch了!");
e.printStackTrace();
}
}
}
另外,还可以通过retuen的方法来中断线程。不过还是建议"抛异常"的方法来实现线程的停止,因为在catch块中还可以将异常向上抛,使线程停止的事件得以传播。
6、Thread.yield()方法:放弃当前的CPU资源,将它让给其他的任务去占用CPU的执行时间。但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。
7、setPriority()方法:为了程序的可移植性,建议植使用 MAX_PRIORITY , NORM_PRIORITY , MIN_PRIORITY 三个级别。设置优先级并不意味着优先级低的就得不到调用,只是CPU更倾向于让高的优先级先执行,但是CPU具体调用那个线程是无法确定的,设置优先级只能保证说这个线程被调用的频率比较高。
8、setDaemon(true):守护线程。守护线程是一个特殊的线程,它的特性有“陪伴”的含义,当进程中不存在非守护线程了,则守护线程自动销毁。典型的守护线程就是垃圾回收线程,当进程中没有非守护线程了,则垃圾回收线程也就没有存在的必要了。
9、join()方法:等待该线程终止。join() 方法主要是让调用该方法的thread完成run方法里面的东西后, 再执行join()方法后面的代码,对join()方法的调用可以被中断,做法是调用线程上的的interrupt()方法。
六、其他
1、stop()方法在终结一个线程时不会保证线程的资源正常释放,通常是没有给予线程完成资源释放工作的机会,因此会导致程序可能工作在不确定状态下。
2、suspend()方法暂停线程。resume()方法恢复线程的执行。在使用 suspend() 和resume()时,线程不会释放已经占有的资源(比如锁),而是占有着资源进入睡眠状态,这样容易引发死锁问题 。这是一个典型的线程对立的例子,如果有两个线程同时持有一个线程对象,一个尝试去中断线程,另一个尝试去恢复线程,如果并发进行的话,无论调用时是否进行了同步,目标线程都是存在死锁风险的。
3、以上提到的原因导致 stop()、suspend()、resume() 被废弃,不建议使用。
3、Daemon 线程是一种支持型线程,主要用作程序中后台调度以及支持性工作。JVM 不存在非 Daemon 线程的时候,Java 虚拟机将会退出。所以不能依靠 Daemon 线程的 finally 块来确保执行关闭或清理资源的逻辑。
4. 启线程前,最好为这个线程设置线程名字,因为这样在使用 jstack 分析程序或者问题排查时,能够找到一个切入点。
多线程编程学习一(Java多线程的基础).的更多相关文章
- Java多线程编程核心技术(一)Java多线程技能
1.进程和线程 一个程序就是一个进程,而一个程序中的多个任务则被称为线程. 进程是表示资源分配的基本单位,线程是进程中执行运算的最小单位,亦是调度运行的基本单位. 举个例子: 打开你的计算机上的任务管 ...
- 多线程编程学习六(Java 中的阻塞队列).
介绍 阻塞队列(BlockingQueue)是指当队列满时,队列会阻塞插入元素的线程,直到队列不满:当队列空时,队列会阻塞获得元素的线程,直到队列变非空.阻塞队列就是生产者用来存放元素.消费者用来获取 ...
- Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) JAVA日志的前世今生 .NET MVC采用SignalR更新在线用户数 C#多线程编程系列(五)- 使用任务并行库 C#多线程编程系列(三)- 线程同步 C#多线程编程系列(二)- 线程基础 C#多线程编程系列(一)- 简介
Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) 一.前言 由于本篇文章较长,所以下面给出内容目录方便跳转阅读,当然也可以用博客页面最右侧的文章目录导航栏进行跳转查阅. 一.前言 ...
- [Java123] JDBC and Multi-Threading 多线程编程学习笔记
项目实际需求:DB交互使用多线程实现 多线程编程基础:1.5 :( (假设总分10) 计划一个半月从头学习梳理Java多线程编程基础以及Oracle数据库交互相关的多线程实现 学习如何通过代码去验证 ...
- 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端
接上文 多线程编程学习笔记——使用异步IO 二. 编写一个异步的HTTP服务器和客户端 本节展示了如何编写一个简单的异步HTTP服务器. 1.程序代码如下. using System; using ...
- 多线程编程学习笔记——async和await(一)
接上文 多线程编程学习笔记——任务并行库(一) 接上文 多线程编程学习笔记——任务并行库(二) 接上文 多线程编程学习笔记——任务并行库(三) 接上文 多线程编程学习笔记——任务并行库(四) 通过前面 ...
- 多线程编程学习笔记——async和await(二)
接上文 多线程编程学习笔记——async和await(一) 三. 对连续的异步任务使用await操作符 本示例学习如何阅读有多个await方法方法时,程序的实际流程是怎么样的,理解await的异步 ...
- 多线程编程学习笔记——async和await(三)
接上文 多线程编程学习笔记——async和await(一) 接上文 多线程编程学习笔记——async和await(二) 五. 处理异步操作中的异常 本示例学习如何在异步函数中处理异常,学习如何对多 ...
- 多线程编程学习笔记——使用异步IO(一)
接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...
随机推荐
- vue数据驱动作用域问题
需求是这样的,如图 点击禁用后,变成启用,但是结果却不让人满意 我们先来看一下错误代码: //conponet控件里的内容 html内容: <div> <button @click. ...
- HTML5 开发APP(MUI的一些特性)
先附mui文档地址:http://dev.dcloud.net.cn/mui/ui/ .mui的UI组件比较简单而且在文档中很好找就不过多说了. 1 在app开发中,使用HTML5+的api,必须m ...
- C# 对xml进行操作
一:xml的基本操作 (1)获得xml文件中的数据 //创建xml文档对象 XmlDocument xmlDoc = new XmlDocument(); //将指定xml文件加载xml文档对象上 x ...
- [Tyvj 1728] 普通平衡树
大名鼎鼎的板子题w 照例先贴题面 Describtion 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. ...
- 初学Python(八)——迭代
初学Python(八)——迭代 初学Python,主要整理一些学习到的知识点,这次是迭代. # -*- coding:utf-8 -*- from collections import Iterabl ...
- 【RegExp】JavaScript中正则表达式判断匹配规则以及常用方法
字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求几乎无处不在. 正则表达式是一种用来匹配字符串的强有力的武器.它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符 ...
- Android中的广播
Android中的广播 广播接受器,可以比喻成收音机.而广播则可以看成电台. Android系统内部相当于已经有一个电台 定义了好多的广播事件,比如外拨电话 短信到来 sd卡状态 电池电量变化... ...
- 5. Leetcode 448. Find All Numbers Disappeared in an Array
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and ot ...
- python常用模块(2)
之前学了两个常用的模块collections和re模块今天我们接着学习其他几个常用模块.都是比较常用的之前的学习或多或少也有所接触比如说时间模块等. 预习: 写一个验证码 首先 要有数字 其次 要有字 ...
- hdu--1421--dp--搬寝室
注意:dp[i][j]初始化的时候不能小于0xffffff明显大于2^15但是吧再小就WA了 #include<iostream> #include<algorithm> #i ...