java中线程总结,JAVA中线程的相关小结
·什么是线程
线程:进程中负责程序执行的执行单元。一个进程中至少有一个线程。
多线程:一个进程中包含有多个线程,但CPU在同一时间只允许一个线程的进行。所以有多个线程的运行是根据CPU切换完成,如何切换由CPU决定,因此多线程运行具有不确定性。
·线程的创建方法
1.继承Thread类
即创建一个thread类,或者创建一个thread子类的对象
1>Thread类的介绍
Thread类是一个线程类,位于java.lang包下
Thread的主要构造方法:
1.1 thread() 创建一个线程对象
1.2 thread(String name) 创建一个具有指定名称的线程对象
1.3 thread(Runnable target) 创建一个基于runnable接口实现类的线程对象
1.4 thread(Runnable target,string name) 创建一个基于Runnable接口实现类,并且具有指定名称的线程对象
常用方法:
1.1 public void run() 线程相关的代码写在该方法中,一般需要重写
1.2 public void start() 启动线程
1.3 public static void sleep(long m) 线程休眠m毫秒
1.4 public final void join() 优先执行调用join方法的线程
2>具体的代码实现
package _Thread;
class mythread extends Thread{
//重写Run方法
public void run() {
System.out.println(getName()+"线程");
}
}
public class _threadTest {
public static void main(String[] args) {
mythread sr=new mythread();
sr.start;//启动线程
}
}
复制代码
实现结果
然后为了将CPU时间片的轮转体现出来,将加入2个循环如下:
package _Thread;
class mythread extends Thread{
public void run() {
for(int i=1;i<=10;i++)
System.out.println(getName()+"线程"+i+"次");
}
}
public class _threadTest {
public static void main(String[] args) {
mythread sr=new mythread();
sr.start();
for(int i=1;i<=10;i++)
System.out.println("主线程"+i+"次");
}
}
复制代码
两次不同的运行结果:
这说明线程的运行是有cpu随机切换完成的,具有不确定性。
tips:
线程只能启动一次
主方法也是一个线程
2.实现Runnable接口
1>Runnable类的介绍
由于JAVA是不支持多继承的,所以如果一个类已经有一个父类,那么我们就无法通过继承Threadl类来创建线程,此时我们就可以通过实现Runnable接口来完成。Runnable是java中实现线程的接口,它有且只有一个方法Run(),并且任何实现线程功能的类必须实现该接口。
2>具体的代码实现
package _Thread;
class mythread implements Runnable{
public void run() {
System.out.println(Thread.currentThread().getName()+"线程");
/*
由于这里没有继承Thread类中的方法,
所以这里调用Thread中的currentThread()的getName()来获取当前线程的名字
*/
}
}
public class _threadTest {
public static void main(String[] args) {
mythread sr=new mythread();
Thread pr=new Thread(sr);//通过调用Thread类中的含参构造方法来创建一个线程对象
pr.start();
}
}
复制代码
tips:一个实例可以被多个线程所共享,一般用于多个线程处理同一个资源的情况。
·线程的状态和生命周期
1.线程的几种状态
1.1新建(NEW)状态
复制代码
当程序使用new关键字创建了一个线程之后,该线程就处于新建状态.
1.2可运行(Runnable)状态
复制代码
该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。
·关于直接调用run()方法
如果直接调用线程对象的run方法,也就是相当于启动线程,并直接执行run方法,而且再run方法结束之前无法运行其他线程。
1.3正在运行(Runnming)状态
复制代码
当CPU开始调度处于可运行状态的线程时,此时线程获得了CPU的时间片才得以真正开始执行run()方法的线程执行体,则该线程处于可运行状态。
1.4阻塞(Blocked)状态
复制代码
处于运行状态的线程在某些情况下,让出CPU并暂时停止该线程的运行,也就是进入了阻塞状态。
1.5终止(Dead)状态
复制代码
线程的run()或call()方法执行完成,线程会正常结束;
线程抛出了一个未捕获的Exception或Errorl异常,线程会意外终止;
或者直接调用该线程stop()方法来结束该线程,但可能会导致线程的死锁;
2.线程的生命周期
线程的生命周期实际上是指线程的几种状态的之间的切换。
生命周期图如下:
这些状态的切换往往是通过调用Thread类中的方法来实现的,下面介绍几种常用的方法:
2.1 public static native void sleep(long millis)
复制代码作用:使当前正在运行的线程休眠millis毫秒
由于该线程是从运行状态到阻塞状态,再到可运行状态,并不是直接到可运行状态。所以中间会产生一定的时间误差,使其略长于所设参数。
该方法是在Thread类中的一个静态方法。
2.2 object.wait()
复制代码作用:暂停该线程,释放对象锁
该方法是在object类中的方法
在调用前需要先拥有某对象的锁,所以一般在 synchronized 同步块中使用
·对象锁简单的理解就是在代码中的方法上加了synchronized的锁,或者synchronized(this)的代码段
于之对应的还有类锁,指在代码中的方法上加了static和synchronized的锁(在下面还会详细涉及到)。
2.3 Thread.yield()
复制代码作用:表示暂停当前线程,让出 CPU给优先级与当前线程相同,或者优先级比当前线程更高的就绪状态的线程。
需要注意的是这和 sleep() 方法不同的是,它不会进入到阻塞状态,而是直接进入到可运行状态。
2.4 Thread.join()
复制代码会优先将该线程运行完毕,再去调用其他线程,也就是等待该线程的终止
其重载方法还有
public final void join(long millis)等待该线程终止的时间最长为 millis 毫秒
public final void join(long millis, int nanos)等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒
·线程的优先级
Java 把线程优先级分成10个级别(依次为1到10,数字越大线程的优先级越高),线程被创建时如果没有明确声明则使用默认优先级(5)。虽然优先级越高越先被执行,但我们不能用线程优先级来规定线程的执行顺序。因为线程的执行顺序还受很多其他因素影响,例如操作系统和JVM的调度等等,所以我们只能说线程优先级越大,越先被执行的可能性越高。这里也体现了CPU调度的随机性。
1.三个优先级的常量
最小优先级(1)=Thread.MIN_PRIORITY
默认优先级(5)=Thread.NORM_PRIORITY
最大优先级(10)=Thread.MAX_PRIORITY
2.优先级的相关方法
2.1 public int getPriority()
复制代码作用:取得线程的优先级
2.2 public void setPriority(int newPriority)
复制代码作用:设置线程的优先级
·线程的同步
由于线程被执行的时间、占用cpu的时间都是不确定的,所以在有多个线程要被执行的情况下,会产生许多问题。例,在有两个线程(线程1和线程2)对同一个类的属性进行操作时,如果线程1对该属性进行“加”的操作前,线程2突然抢占了CPU来对该属性进行了“减”的操作,对该属性进行修改,那么就可能出现类似于1+1=1的结果。
为了避免上述结果的出现,这里需要调用一个synchronized关键字(同步),来对该共享对象进行上锁,即让该共享对象在同一个时刻,只能被一个线程访问。
synchronized关键字的使用
一般加在线程前,表明该线程不允许被打断,
可以加在静态方法/方法/语句块前。
例:
public synchronized void 方法名(){}
复制代码public static synchronized void 方法名(){}
复制代码synchronized(对象名){}
复制代码
线程间的通信
我们先引进三个方法
wait()中断方法的执行,使线程等待
复制代码notify()随机唤醒等待的某一个线程
复制代码notifyall()唤醒所有处于等待的线程
复制代码
对多线程的处理,下面以对2个线程的处理为例
一般是将公共对象当作一个容器queue,并在该容器内设置一个Boolean类型的值,在将线程1和2设置为synchronized类型后,在线程1中添加判断语句,如果该Boolean型值为ture(也可以是flase)才能执行该线程的操作语句,否则进入等待(在这里调用wait()使其暂停运行,记得要在线程最后改变Boolean类型值的值),对线程2的操作也类似,这样就能解决对线程调度顺序问题。
但这样问题并不是完全被解决,如果线程1和2都进入休眠状态,那么锁死,即两个线程都不进行。所以我们还需要在线程1和线程2的最后加上唤醒醒另一个线程的语句(这里调用notifyall(),之所以不调用notify()是因为它是随机唤醒某一个线程,如果在程序中还有线程3、线程4···,那我们想唤醒的线程有可能不被唤醒)
java中线程总结,JAVA中线程的相关小结相关推荐
- Java中创建线程需要使用的类_如何通过使用Java中的匿名类创建线程?
甲线程是可以同时与该程序的其他部分被执行的功能.所有Java程序都有至少一个称为主线程的线程,该线程由Java虚拟机(JVM)在程序启动时由主线程调用main()方法创建. 在Java中,我们可以通过 ...
- java闭合数据_java多线程中线程封闭详解
线程封闭的概念 访问共享变量时,通常要使用同步,所以避免使用同步的方法就是减少共享数据的使用,这种技术就是线程封闭. 实现线程封闭的方法 1:ad-hoc线程封闭 这是完全靠实现者控制的线程封闭,他的 ...
- java 中如何正确的停止线程
如何优雅的停止一个线程 1.为什么要停止线程 2.为何说要正确的停止线程 3.使用interrupt()停止线程 4.线程在通常三种情况下停止 4.1 普通情况 4.2 线程阻塞情况 4.3 传递中断 ...
- 每个java程序都至少有一个线程给主线程,java程序在主线程中判断各个子线程状态的操作,该如何解决...
java程序在主线程中判断各个子线程状态的操作 每个子线程在队列为空时会wait等待其他线程添加新url到队列,到最后所有子线程都取不到url时也会都wait住,要在主线程中判断如果所有的子线程都是w ...
- java 线程 状态 图_Java线程中的生命周期和状态控制图文详解
这篇文章主要介绍了Java线程的生命周期和状态控制,需要的朋友可以参考下 一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于 ...
- java 线程aba,JAVA中CAS-ABA的问题解决方案AtomicStampedReference
了解CAS(Compare-And-Swap) CAS即对比交换,它在保证数据原子性的前提下尽可能的减少了锁的使用,很多编程语言或者系统实现上都大量的使用了CAS. JAVA中CAS的实现 JAVA中 ...
- java中定时任务和线程池_java基于线程池和反射机制实现定时任务完整实例
本文实例讲述了java基于线程池和反射机制实现定时任务的方法.分享给大家供大家参考,具体如下: 主要包括如下实现类: 1. Main类: 任务执行的入口: 调用main方法,开始加载任务配置并执行任务 ...
- java线程中的常用方法_[多线程] 线程中的常用方法-最详细
线程中常用的方法 1.public void start() 使该线程开始执行:Java 虚拟机调用该线程的 run 方法. 2.public void run() 如果该线程是使用独立的 Runna ...
- JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor
http://www.diybl.com/course/3_program/java/javajs/200797/70003.html 在多线程大师Doug Lea的贡献下,在JDK1.5中加入了许多 ...
- 京东面试题:Java中 ++i 的操作是线程安全的么?为什么?如何使其线程安全呢?
转载自 相关文章 你真的了解volatile关键字吗?http://blog.csdn.net/FansUnion/article/details/79495080 面试题:为什么最后两行没有运行?h ...
最新文章
- VisualStudio 合并代码文件
- RHEL 5服务篇—使用Apache搭建Web服务(一)
- 将隐式神经表示(INR)用于2D图像
- SSH连接linux时,长时间不操作就断开的解决方案
- 浅谈opencl之错误码
- MySQL--流程控制
- Windows 会有开源的一天吗?
- android 浏览器抓包工具下载,WebSee app下载-WebSee抓包工具v1.2.1 安卓版-腾牛安卓网...
- kcp参数 android,Android上KCP协议的使用
- 平面几何----用角平分线逆定理证明阿氏圆定理
- 解决 DevExpress21 控件不在工具箱显示问题
- java数字金额大写金额_Java实现 “ 将数字金额转为大写中文金额 ”
- python 波动率锥_期权波动率期限结构与日历价差策略
- iPhone 4S版本查看
- h5(移动端) 监听软键盘弹起、收起
- java.dll_ibtmjava.dll,下载,简介,描述,修复,等相关问题一站搞定_DLL之家
- ubuntu16.04虚拟win7——经验笔记——问题:Kernel driver not installed (rc=1908) error.
- 数学建模入门例题python_Python 数学建模极简入门(一)
- Tera term串口下发AT命令测试
- 前端文本对比工具使用 - mergely