一. Java线程具有6种状态

 NEW 初始状态,线程被创建,但是还没有调用start方法。
RUNNABLE 运行状态,java线程将操作系统中的就绪和运行两种状态笼统的称作进行中。
BLOCKED 阻塞状态,表示线程阻塞于锁。
WAITING 等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程做出一些其它动作
TIME_WAITING 超时等待状态,该状态不同于WAITING,它是可以在指定的时间自动返回的
TERMINATED 终止状态,表示当前线程已经执行完毕

二. 线程的优先级

线程通过一个整形变量priority来控制修改优先级,优先级的范围从1-10,在线程构建的时候可以通过setPriority(int)方法来修改优先级,默认的优先级是5,理论上优先级别高的线程分配的时间片会多,在不同的JVM以及操作系统上,线程的规划会存在差异,有些操作系统甚至会忽略对线程优先级的设定。

线程优先级不能作为程序正确性的依赖,因为操作系统可以完全不用理会java线程优先级的设定。

三. Daemon线程

Daemon线程是一种支持型的线程,因为它主要被用作程序中后台调度以及支持性工作。

Daemon线程需要在启动线程之前设定,不能在启动之后设定。

在创建Daemon线程时,不能依靠finally块中的内容来确保执行关闭或清理资源的逻辑。

package com.bochao.concurrency;

public class Daemon {

	static class DaemonRunner implements Runnable {

		@Override
public void run() { try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 在创建Daemon线程时,不能依靠finally块中的内容来确保执行关闭或清理资源的逻辑。
System.out.println("DaemonThread finally run.");
}
}
} public static void main(String[] args) { Thread thread = new Thread(new DaemonRunner(), "DaemonRunner");
//thread.setDaemon(true); // 守护线程
thread.start();
} }

四. 线程启动和终止

线程运行:线程在初始化完成后,调用start()方法就可以启动这个线程。(启动一个线程前,最好为这个线程设定一个线程名称,在使用jstack分析程序时会有帮助)

线程中断:中断可以理解为线程的一个标识位属性,它表示一个运行中的线程是否被其他线程进行了中断操作,其它线程通过调用interrupt()方法对其进行中断操作。线程通过方法isInterrupted()来进行判断是否被中断,也可以调用静态方法Thread.interrupted()对当前线程的中断标识位进行复位。

五. 过期suspend, 恢复resume,停止stop

这三个方法分别可以对线程进行暂停、恢复、停止,但是API是过期的,也就是不建议使用。也就是这些方法存在着一定的弊端。

六. 安全的终止线程

Java中一种比较安全和优雅的方式使用一个boolean值来终止一个线程运行。

package com.bochao.concurrency;

import java.util.concurrent.TimeUnit;

public class Shutdown {

	private static class Runner implements Runnable{

		private long i;

		private volatile boolean on = true;

		@Override
public void run() { while(on && !Thread.currentThread().isInterrupted()){
i++;
}
System.out.println("Count i = " + i);
} public void cancle(){
on = false;
}
} public static void main(String[] args) { Runner runner = new Runner();
Thread countThread = new Thread(runner, "CountThread");
countThread.start(); try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
} countThread.interrupt(); Runner runner2 = new Runner();
Thread countThread2 = new Thread(runner2, "CountThread");
countThread2.start(); try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} runner2.cancle();
} }

 七.  线程间通信
线程拥有自己的堆栈,线程间的通信机制,为java多线程带来了巨大的价值。

volatile和synchronized关键字

volatile关键字:可以用来修改字段或者变量,就是告知程序任何对该变量的访问均需要从共享内存中获取,而对它的改变必须同步刷新回共享内存,他能保证所有线程对变量访问的可见性。但是过多的使用会造成程序执行效率低下。

synchronized关键字:可以修饰方法或以同步快的形式使用,它主要是保证多个线程在同一时刻,只能有一个线程处于方法或同步快中,它保证了线程对变量访问的可见性和排它性。

八. 等待和通知机制

wait, notify, notifyAll 等待, 通知,通知全部

等待和通知机制,是指一个线程A调用了对象O的wait()方法进入等待状态,而另一个线程B调用了对象O的nofity()或者notifyAll()方法,线程A收到通知后从对象的wait()方法返回,进而执行后续操作。

package com.bochao.concurrent;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit; public class WaitNofity { private static boolean keepWait = true;
private static Object lock = new Object(); // 等待
static class Wait implements Runnable{ @Override
public void run() {
// 上锁,获得lock的Monitor
synchronized (lock) {
// 判断条件
while(keepWait){
System.out.println(Thread.currentThread() + " keepWait is true. wait@"
+ " " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 条件满足,开始工作
System.out.println(Thread.currentThread() +" keepWait is false. running@"
+ " " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}
} // 通知
static class Notify implements Runnable{ @Override
public void run() { // 上锁,获得lock的Monitor
synchronized (lock) {
// 获得lock的锁,然后进行通知,通知(notifyAll()后)不会立即施放lock的锁,
// 直到当前线程施放lock,WaitThead才能从wait方法中返回
System.out.println(Thread.currentThread() + " hold lock. notify @ "
+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.notifyAll();
keepWait = false;
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 再次加锁
synchronized (lock) {
System.out.println(Thread.currentThread() + " hold lock again. sleep @ "
+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} } public static void main(String[] args) throws InterruptedException { // 等待
Thread waitThread = new Thread(new Wait(), "WaitThead");
waitThread.start();
TimeUnit.SECONDS.sleep(1); // 通知
Thread notifyThread = new Thread(new Notify(), "NotifyThread");
notifyThread.start();
} }

注意:

1. 使用wait, nofity, notifyAll需要先对调用对象加锁。

2. 调用wait()方法后,线程状态由RUNNING变为WAITING,并将当前线程放置到对象的等待队列。

3. notify()或notifyAll()方法调用后,等待线程依旧不会从wait()返回,需要调用notify()或notifyAll()的线程施放锁之后,等待线程才有机会从wait()返回。

4. notify()方法将等待队列中一个等待的线程从等待队列中移到同步队列中,而notifyAll()方法是将等待队列中的所有线程全部移动到同步队列,被移动的线程从WAITING变为BLOCKED。

5. 从wait()方法返回的前提是获得了调用对象的锁。

等待通知经典范式

即生产者和消费者模式

1. 消费者遵循如下原则:

(1). 获取对象的锁

(2). 如果条件不满足,那么调用对象的wait()方法,被通知方仍要检查条件

(3). 条件满足则执行对象的逻辑

synchronized(对象){
while(条件不满足){
对象.wait();
}
// 对应的处理逻辑
}

2. 生产者遵循如下原则:

(1). 获得对象的锁

(2). 改变条件

(3). 通知所有等待在对象上的线程

synchronized(对象){
改变条件
对象.notifyAll();
}

Java多线程基础知识(二)的更多相关文章

  1. Java 多线程——基础知识

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  2. Java多线程基础知识笔记(持续更新)

    多线程基础知识笔记 一.线程 1.基本概念 程序(program):是为完成特定任务.用某种语言编写的一组指令的集合.即指一段静态的代码,静态对象. 进程(process):是程序的一次执行过程,或是 ...

  3. Java多线程基础知识总结

    2016-07-18 15:40:51 Java 多线程基础 1. 线程和进程 1.1 进程的概念 进程是表示资源分配的基本单位,又是调度运行的基本单位.例如,用户运行自己的程序,系统就创建一个进程, ...

  4. JAVA多线程基础知识(一)

    一. 基础知识 要了解多线程首先要知道一些必要的概念,如进程,线程等等.开发多线程的程序有利于充分的利用系统资源(CPU资源),使你的程序执行的更快,响应更及时. 1. 进程,一般是指程序或者任务的执 ...

  5. Java多线程基础知识篇

    这篇是Java多线程基本用法的一个总结. 本篇文章会从一下几个方面来说明Java多线程的基本用法: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 所有的代码 ...

  6. Java多线程基础知识例子

    一.管理 1.创建线程 Thread public class Main { public static void main(String[] args) { MyThread myThread = ...

  7. JAVA多线程基础学习二:synchronized

    本篇主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题,没错就是使用synchronized. 一.如何解决线程安全问题? 一般 ...

  8. Java多线程基础知识总结笔记

    本篇笔记记录一些在Java多线程编程中常见的关键字,比较简单和基础的就不写太详细了. 一.Thread类(其实也是应用了Runnable接口)和Runnable接口(只有一个run方法,应用该类必须重 ...

  9. Java多线程-基础知识

    一. 进程是执行中的程序,程序是静态的(我们写完以后不运行就一直放在那里),进程是执行中的程序,是动态概念的.一个进程可以有多个线程. 二. 多线程包含两个或两个以上并发运行的部分,把程序中每个这样并 ...

随机推荐

  1. 【突发问题】昨天更新了OS X EI Capitan 出现了Cocoapods的 pod :command not found

    然后我百度:http://www.jianshu.com/p/6ff1903c3f11 果真,我想想然后执行了作者说的第一步,删除本地Cocoapods文件,然后发现我执行不了接下来的几个步骤了.所以 ...

  2. HDU5672String(尺标法)

    问题描述 有一个 10\leq10≤长度\leq 1,000,000≤1,000,000 的字符串,仅由小写字母构成.求有多少个子串,包含有至少k(1 \leq k \leq 26)k(1≤k≤26) ...

  3. 强大的css3

    强大的css3 我们知道,这几年来智能手机的高速发展使得人们使用移动端上网的时间和人数已经超过了PC端.例如在2015年,就中国电商而言,各电商平台在移动端持续发力,移动端购物占比不断攀升,双11期间 ...

  4. CSS3的transition动画功能

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  5. win7怎么显示隐藏文件夹

    1. 点击“组织”,再选择“文件夹和搜索选项”命令. 2. 接下来在打开的“文件夹选项”对话框中,单击“查看”,切换到“查看”选项卡中. 3. 然后在下面的“高级设置”区域,取消“隐藏受保护的操作系统 ...

  6. super 要点

    class Grandparent { public Grandparent() { System.out.println("GrandParent Created."); } p ...

  7. C++中public,protected,private派生类继承问题和访问权限问题

    C++中public,protected,private派生类继承问题和访问权限问题 当一个子类从父类继承时,父类的所有成员成为子类的成员,此时对父类成员的访问状态由继承时使用的继承限定符决定. 1. ...

  8. Latex 表格内公式换行方法

    Latex 表格内的公式实现换行的方法       简单的两步走:   1.先将下面的语句放在latex正文的导言区: \newcommand{\tabincell}[2]{\begin{tabula ...

  9. 居于Web的进度条实现思路(下载百分比)

    http://www.cnblogs.com/wfyfngu/p/4866434.html 在传统桌面项目中,进度条随处可见,但作为一个很好的用户体验,却没有在如今主流的B/S程序中得到传承,不能不说 ...

  10. MVC中 _ViewStart _Layout Index三个页面中的加载顺序

    MVC学习中忽然想到一个问题.. 在访问一个Index.cshtml页面时, MVC的加载顺序是怎么样的呢? 首先说下我的结论 . _ViewStart.cshtml . Index.cshtml . ...