程序:静态的代码
进程:正在运行的程序
用于管理所有资源,不进行实际的任务
线程:完成具体任务(一个进程里有多个线程)
比如:qq运行后就是一个进程---和一个好友聊天(一个线程)---其他操作(也是一个个线程)
开启一个线程
主线程:java中,main方法里面的代码就是在主线程
Android/IOS,ui界面-ui主线程
子线程:除了主线程之外的都是子线程
为什么要使用多线程
在主线程中,代码的执行是顺序是从上到下,如果其中一个任务需要大量时间,这个任务就会阻塞后面任务,导致用户体验不好,所以将耗时的任务放在一个子线程中执行
线程是通过抢占时间片来获取运行机会的
时间片通过操作系统分配时间片,所以每次执行结果可能不一致
如何开启一个线程
打印Thread.currentThread();可查看信息---名字,优先级(最高为5)
方法一:
1.写一个类继承Thread
2.实现run方法,写入线程需要执行的任务
3.创建对象调用start方法开始执行run方法里的任务(系统会自动将这个任务放到队列中等待调度)
方法二:
1.写一个类实现runnable接口(这个类只是一个任务,不能创建线程,需要依赖于Thread类创建线程)
2.创建具体的对象并传递给new Thread()方法(关联起来)
3.使用Thread类的start方法启动线程
使用匿名内部类
Thread test = new Thread(new Runnable(){
代码块
}).start();
当调用start时,这个线程会自动扔到操作系统的任务队列中(线程池)
至于什么时候执行,由操作系统决定
两种方法优缺点:
使用接口可以多继承,灵活易扩展,松耦合
线程的生命周期
主线程和子线程都有自己的生命周期(创建到结束)
创建状态:new Thread()
就绪状态:
1.新的线程调用start()
2.阻塞条件结束
3.正在运行的时间片被其他线程抢走
运行状态:从就绪状态到运行状态由系统控制
死亡状态:
1.run方法结束
2.手动让线程暂停,不建议使用stop,通过其他方式让线程暂停
阻塞状态
getState方法可以查看线程的状态(NEW ,RUNNABLE ,BLOCKED ,WAITING ,TIMED_WAITING ,TERMINATED)
如何让一个线程结束:
1.不要直接调用stop方法
2.自己写一个变量/标识符,用来标记线程结束的临界点(比如用bool类型变量来控制是否结束)
线程的礼让以及插队
礼让(yield) 当前线程会进入就绪状态,如果得到系统分配的时间片,又进入运行状态,所以有可能礼让失败
插队(join)当前线程一直运行到死亡状态,其他线程阻塞
多线程的优缺点
优点:效率高,主线程不会阻塞
缺点:如果多个线程操作一个资源,可能不安全
保证线程安全
1.lock 必须使用同一个锁
private static Lock lock = new ReentrantLock();
lock.lock();
代码块
lock.unlock();
2.线程同步 synchronized
代码块 方法
必须保证锁的是同一个对象,每一个对象都维护一把锁
private static Object obj = new Object();
synchronized(obj){
代码块
}
锁的代码块尽量小
线程之间的通信
A - B
wait() 让某个线程等待
notify()唤醒线程
notifyAll()唤醒多个线程
注意:这三个方法必须由同步监视器调用
要使两个线程分别交替输出
第一种
先定义静态变量static Object obj = new Object();
static int state = 1;
state为1表示第一条线程执行,2表示第二条线程执行
public class threads{
static int state = 1;
static Object obj = new Object();
public static void main(String[] args) {
new Thread(new Runnable(){
int num = 1;
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
synchronized(obj){
if(state != 1){
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(num++);
obj.notify();
state = 2;
if(num > 26){
break;
}
}
}
}
}).start();
new Thread(new Runnable(){
char alpha = 'a';
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
synchronized(obj){
if(state != 2){
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(alpha++);
if(alpha > 'z'){
break;
}
}
}
}
}).start();
}
}
结果将交替输出数字和字母
第二种
class Date{
int state = 1;
int Num = 1;
char alpha = 'a';
public synchronized void printNum(){
while(true){
if(state != 1){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Num++);
this.notify();
state = 2;
if(Num >26){
break;
}
}
}
public synchronized void printChar(){
while(true){
if(state != 2){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(alpha++);
this.notify();
state = 1;
if(alpha > 'z'){
break;
}
}
}
}
public class other {
static Date date = new Date();
public static void main(String args[]){
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
date.printNum();
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
date.printChar();
}
}).start();
}
}