一,概念
当代操作系统中,可以独立并发执行的基本单元。
轻量:占用系统资源少
独立:操作系统中可以陆地调度和分派的基本单位
共享:共享进程中的资源
二,实现线程
更推荐集成Runnable接口方式?
三,线程生命周期
新建:线程刚刚创建完毕
可运行:启动线程后
运行:操作系统调度中
阻塞/等待:等待资源或者时间片
消亡:退出run方法
四,常用API
静态 针对当前进程
currentThread
yield
sleep
实例方法 针对指定线程
start
setPriority/getPriority(1-10 不设置是5 不一定高优先级就能先执行)
setName/getName
setDaemon/isDaemon(守护线程是其他线程结束之后自动消亡的线程)
五,线程同步
/*
* DESCRIPTION :
* USER : zhouhui
* DATE : 2017/8/1 15:50
*/
public class SynchronizedTest {
/**
* method1:对方法进行锁
*/
public synchronized void method1(){
}
/**
* method2:对当前对象锁
*/
public void method2(){
synchronized (this){
}
}
/**
*method3:对当前对象锁
*/
public void method3(){
synchronized (SynchronizedTest.this){
}
}
/**
*method4:对静态方法锁
* 静态方法属于类,所以是对类上锁
*/
public synchronized static void method4(){
}
/**
*method5:对class锁
*/
public static void method5(){
synchronized (SynchronizedTest.class){
}
}
/**
* method6:对成员变量锁
*/
private Integer i = 0;
public void method6(){
synchronized (i){
}
}
}Java语法规定,任何线程执行同步方法、同步代码块 之前,必须先获取对应的监视器。
其中method1,method2,method3都是对当前对象上锁。
method4,method5对当前类上锁
method6是对属性上锁。
对方法上锁和对代码块上锁的区别是,如果方法太大,对方法上锁的开销要大的多。
method2和method6的区别:
public class Test {
public static void main(String[] args) {
Data data = new Data();
new Thread(new MyRunnable(data),"A").start();
new Thread(new MyRunnable(data),"B").start();
}
}
class Data{
private Integer i = 0;
public void show(){
while (true){
synchronized (i){
if(i == 30){
break;
}
System.out.println(Thread.currentThread().getName() + " Before :" + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
i ++;
System.out.println(Thread.currentThread().getName() + " After :" + i);
}
}
}
}
class MyRunnable implements Runnable{
private Data data;
public MyRunnable(Data data){
this.data = data;
}
public void run() {
data.show();
}
}synchronized (i){
和
synchronized (this){
会产生不同的结果。
对this上锁能够正常的在30时停止,对i上锁会打印如下:
A Before :0 A After :1 B Before :1 A Before :1 A After :2 A Before :2 B After :3 B Before :3 B After :4 A After :5 B Before :5 B After :6 B Before :6 A Before :6 A After :7 A Before :7 B After :8 B Before :8 B After :9 A After :9 B Before :9 B After :10 B Before :10 A Before :10 A After :11 A Before :12 B After :12 A After :13 B Before :13 A Before :13 A After :15 B After :15 A Before :15 A After :16 B Before :16 A Before :16 A After :17 A Before :17 B After :18 B Before :18 A After :19 A Before :19 B After :20 B Before :20 A After :21 A Before :21 B After :22 B Before :22 A After :23 A Before :23 B After :24 B Before :24 A After :25 A Before :25 B After :26 B Before :26 A After :27 A Before :27 B After :28 B Before :28 A After :29 A Before :29 B After :30 A After :31 A Before :31 A After :32 A Before :32 A After :33 A Before :33 A After :34 A Before :34 A After :35 A Before :35
但是有时候是可以成功的。
如果对i上锁,能够保证同一时间只能一个线程对i进行操作。如果一个线程能够在另外一个线程i++之前获得i那么,他是能够正常i==30停止的,但是如果在另外一个线程i++之后获得i那么,他就会直接跳过30,而继续运行。
对this上锁,意味着对整个对象上锁,只能一个线程操作代码块,保证数据的完整性。
六,线程间通信
Object对象提供了wait() notify() notifyAll()方法,被所有子类继承。
wait()获得当前对象锁的线程,释放掉当前的锁,无限期的等待,必须被其他的线程唤醒。
notify() 唤醒任意一个waiting的线程到ready状态,是否变成running状态,还需要线程调度器的调度。
notifyAll()唤醒所有的waiting的线程到ready状态。
线程间的通信其实就是停止和唤醒的过程。
以下代码实现两个线程对同一个对象的+1和-1操作,相互停止和唤醒。
/*
* DESCRIPTION :
* USER : zhouhui
* DATE : 2017/8/1 17:28
*/
public class NumberHolder {
private int number;
public synchronized void increase() {
if (0 != number) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 能执行到这里说明已经被唤醒
// 并且number为0
number++;
System.out.println(number);
// 通知在等待的线程
notify();
}
public synchronized void decrease() {
if (0 == number) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 能执行到这里说明已经被唤醒
// 并且number不为0
number--;
System.out.println(number);
notify();
}
}
class IncreaseThread extends Thread {
private NumberHolder numberHolder;
public IncreaseThread(NumberHolder numberHolder) {
this.numberHolder = numberHolder;
}
@Override
public void run() {
for (int i = 0; i < 20; ++i) {
// 进行一定的延时
try {
Thread.sleep((long) Math.random() * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 进行增加操作
numberHolder.increase();
}
}
}
class DecreaseThread extends Thread {
private NumberHolder numberHolder;
public DecreaseThread(NumberHolder numberHolder) {
this.numberHolder = numberHolder;
}
@Override
public void run() {
for (int i = 0; i < 20; ++i) {
// 进行一定的延时
try {
Thread.sleep((long) Math.random() * 1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
// 进行减少操作
numberHolder.decrease();
}
}
}
class NumberTest {
public static void main(String[] args) {
NumberHolder numberHolder = new NumberHolder();
Thread t1 = new IncreaseThread(numberHolder);
Thread t2 = new DecreaseThread(numberHolder);
t1.start();
t2.start();
}
}打印结果:
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
原文地址:http://13172906.blog.51cto.com/13162906/1952748