·什么是线程

线程:进程中负责程序执行的执行单元。一个进程中至少有一个线程。

多线程:一个进程中包含有多个线程,但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中线程的相关小结相关推荐

  1. Java中创建线程需要使用的类_如何通过使用Java中的匿名类创建线程?

    甲线程是可以同时与该程序的其他部分被执行的功能.所有Java程序都有至少一个称为主线程的线程,该线程由Java虚拟机(JVM)在程序启动时由主线程调用main()方法创建. 在Java中,我们可以通过 ...

  2. java闭合数据_java多线程中线程封闭详解

    线程封闭的概念 访问共享变量时,通常要使用同步,所以避免使用同步的方法就是减少共享数据的使用,这种技术就是线程封闭. 实现线程封闭的方法 1:ad-hoc线程封闭 这是完全靠实现者控制的线程封闭,他的 ...

  3. java 中如何正确的停止线程

    如何优雅的停止一个线程 1.为什么要停止线程 2.为何说要正确的停止线程 3.使用interrupt()停止线程 4.线程在通常三种情况下停止 4.1 普通情况 4.2 线程阻塞情况 4.3 传递中断 ...

  4. 每个java程序都至少有一个线程给主线程,java程序在主线程中判断各个子线程状态的操作,该如何解决...

    java程序在主线程中判断各个子线程状态的操作 每个子线程在队列为空时会wait等待其他线程添加新url到队列,到最后所有子线程都取不到url时也会都wait住,要在主线程中判断如果所有的子线程都是w ...

  5. java 线程 状态 图_Java线程中的生命周期和状态控制图文详解

    这篇文章主要介绍了Java线程的生命周期和状态控制,需要的朋友可以参考下 一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于 ...

  6. java 线程aba,JAVA中CAS-ABA的问题解决方案AtomicStampedReference

    了解CAS(Compare-And-Swap) CAS即对比交换,它在保证数据原子性的前提下尽可能的减少了锁的使用,很多编程语言或者系统实现上都大量的使用了CAS. JAVA中CAS的实现 JAVA中 ...

  7. java中定时任务和线程池_java基于线程池和反射机制实现定时任务完整实例

    本文实例讲述了java基于线程池和反射机制实现定时任务的方法.分享给大家供大家参考,具体如下: 主要包括如下实现类: 1. Main类: 任务执行的入口: 调用main方法,开始加载任务配置并执行任务 ...

  8. java线程中的常用方法_[多线程] 线程中的常用方法-最详细

    线程中常用的方法 1.public void start() 使该线程开始执行:Java 虚拟机调用该线程的 run 方法. 2.public void run() 如果该线程是使用独立的 Runna ...

  9. JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor

    http://www.diybl.com/course/3_program/java/javajs/200797/70003.html 在多线程大师Doug Lea的贡献下,在JDK1.5中加入了许多 ...

  10. 京东面试题:Java中 ++i 的操作是线程安全的么?为什么?如何使其线程安全呢?

    转载自 相关文章 你真的了解volatile关键字吗?http://blog.csdn.net/FansUnion/article/details/79495080 面试题:为什么最后两行没有运行?h ...

最新文章

  1. VisualStudio 合并代码文件
  2. RHEL 5服务篇—使用Apache搭建Web服务(一)
  3. 将隐式神经表示(INR)用于2D图像
  4. SSH连接linux时,长时间不操作就断开的解决方案
  5. 浅谈opencl之错误码
  6. MySQL--流程控制
  7. Windows 会有开源的一天吗?
  8. android 浏览器抓包工具下载,WebSee app下载-WebSee抓包工具v1.2.1 安卓版-腾牛安卓网...
  9. kcp参数 android,Android上KCP协议的使用
  10. 平面几何----用角平分线逆定理证明阿氏圆定理
  11. 解决 DevExpress21 控件不在工具箱显示问题
  12. java数字金额大写金额_Java实现 “ 将数字金额转为大写中文金额 ”
  13. python 波动率锥_期权波动率期限结构与日历价差策略
  14. iPhone 4S版本查看
  15. h5(移动端) 监听软键盘弹起、收起
  16. java.dll_ibtmjava.dll,下载,简介,描述,修复,等相关问题一站搞定_DLL之家
  17. ubuntu16.04虚拟win7——经验笔记——问题:Kernel driver not installed (rc=1908) error.
  18. 数学建模入门例题python_Python 数学建模极简入门(一)
  19. Tera term串口下发AT命令测试
  20. 前端文本对比工具使用 - mergely

热门文章

  1. DBA+北京社群第三次线下沙龙归来
  2. Qt环境搭建(Visual Studio)
  3. 关于更改apache和mysql的路径的问题..
  4. NTFS格式分区大小数值表
  5. Linux DNS 服务配置 (非常详细)
  6. Compass.net
  7. 动态规划(四)--最长公共子序列
  8. oracle12 group by 拼接字符串
  9. Codeforces Round #510 (Div. 2) AB By cellur925
  10. CodeForces 828E DNA Evolution(树状数组)题解