线程与进程
- 线程:程序中单独顺序的控制流
线程本身依靠程序进行运行 - 进程:执行中的程序
一个进程可以包含一个或多个线程
一个进程至少要包含一个线程 - 单线程:程序中只存在一个线程,实际上主方法就是一个主线程
- 多线程:多线程是在一个程序中运行多个任务
多线程的目的是更好的使用CPU的资源
线程的实现
1 在java中,线程的实现有2种
继承Thread类
实现Runnable接口
2 Thread类:
Thread类是在java.lang包中定义的,继承Thread类必须重写run()方法
定义格式:
class className extends Thread{
run(){};
}
3 Runnable接口,也需要实现其run()方法
线程的状态
线程也有固定的操作状态
- 创建状态:准备好了一个多线程的对象
- 就绪状态:调用了start()方法,等待CPU进行调度
- 运行状态:执行run()方法
- 阻塞状态:暂时停止执行,可能将资源交给其他线程使用
- 终止状态(死亡状态):线程销毁
线程常用方法
- 取得线程名称 getName()
- 取得当前线程对象 currentThread()
- 判断线程是否启动 isAlive()
- 线程强行运行 join()
- 线程休眠 sleep()
demo
package com.test.threaddemo;
/**
* Created by elijahliu on 2017/2/26.
*/
public class threadDemo implements Runnable{
public static void main(String[] args){
threadDemo r1 = new threadDemo("1");
threadDemo r2 = new threadDemo("2");
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
System.out.println(t1.isAlive());//判断线程是否在执行当中
t1.start();
System.out.println(t1.isAlive());
t2.start();
for(int i = 0;i<50;i++) {
if (i > 10) {
try {
// 当主线程的计数大于10时,就把cpu资源让给t1来执行,然后直到t1执行完毕然后继续执行主线程
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private String name;
public threadDemo(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0;i<50;i++) {
//获取当前线程名
System.out.println("当前线程对象:"+Thread.currentThread().getName());
try {
Thread.sleep(1000);//线程沉睡一秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程同步
- 同步代码块
在代码块钱面加上 synchronized 关键字,则此代码就称为同步代码块 - 同步代码块格式
synchronized(同步对象){
需要同步的代码块;
}
- 同步方法
除了代码块可以同步,方法也是可以同步的 - 方法同步格式
synchronize void 方法名(){}
死锁
当线程需要同时持有多个锁时,有可能产生死锁。考虑如下情形:
线程A当前持有互斥所锁lock1,线程B当前持有互斥锁lock2。接下来,当线程A仍然持有lock1时,它试图获取lock2,因为线程B正持有lock2,因此线程A会阻塞等待线程B对lock2的释放。如果此时线程B在持有lock2的时候,也在试图获取lock1,因为线程A正持有lock1,因此线程B会阻塞等待A对lock1的释放。二者都在等待对方所持有锁的释放,而二者却又都没释放自己所持有的锁,这时二者便会一直阻塞下去。这种情形称为死锁。
大部分代码并不容易产生死锁,死锁可能在代码中隐藏相当长的时间,等待不常见的条件地发生,但即使是很小的概率,一旦发生,便可能造成毁灭性的破坏。避免死锁是一件困难的事,遵循以下原则有助于规避死锁:
1、只在必要的最短时间内持有锁,考虑使用同步语句块代替整个同步方法;
2、尽量编写不在同一时刻需要持有多个锁的代码,如果不可避免,则确保线程持有第二个锁的时间尽量短暂;
3、创建和使用一个大锁来代替若干小锁,并把这个锁用于互斥,而不是用作单个对象的对象级别锁;