多线程
进程
程序是指令和数据的有序集合, 其本身没有任何运行的含义, 是一个静态的概念. 而进程是程序在处理机上的一次执行的过程, 它是一个动态的概念.
进程是一个独立功能的程序, 一个实体, 每一个进程都有它自己的地址空间
线程
是在进程基础之上的进一步划分, 一个进程启动之后, 里面的若干程序又可以划分成若干个线程.
定义: 是进程中的一个执行路径, 共享一个内存空间, 线程之间可以自由切换, 并发执行, 一个进程最少有一个线程(单线程程序)
main 运行在主线程中, 当然在子线程中也可以调用main, 此时main就在子线程中运行
Java程序中有两个线程:
主线程和垃圾回收线程
守护线程:
不占用进程
如果进程中只有守护线程的时候进程结束! 可以把线程设置成守护线程, 一般情况下是个死循环
注:垃圾回收线程就是守护线程
实现线程的两种方式
1, 继承Thread类
2, 实现Runnable接口
注: 在Java中只有Thread对象才能启动线程
API知识
Thread thread = Thread.currentThread();//得到当前的线程, 主要是为了确定在哪个线程当中(线程的名字可以相同, 但是ID一定不同)
//System.out.println(thread.getName());//得到线程的名字
//System.out.println(thread.getId());//得到线程的id
System.out.println(thread.getPriority());//得到线程优先级
myThread.setPriority(10);//设置优先级
System.out.println(myThread.getPriority());
myThread.setDaemon(true);//设置成 守护线程
myThread.start();//启动线程
// System.exit(0);//退出整个虚拟机
// myThread.interrupt();//打断线程, 不推荐使用,很难精确打断位置
// 如果唤醒两个线程中wait, 会先唤醒先wait的线程
// 在此情况下, 写两个notify()会唤醒两个wait的线程
synchronized (object) {
//object.notify();唤醒该对象上的wait
object.notifyAll();//唤醒所有, 但是不一定先唤醒哪一个
}
如何停止一个线程?
1, 用myThread.interrupt();打断线程, 不推荐使用,很难精确打断位置, 而且有可能出现异常
2, 常规做法是设置个标记
public class MyThread extends Thread {
private boolean isRunning = true;
public void setRunning(boolean running) {
isRunning = running;
}
@Override
public void run() {
super.run();
while (isRunning){
//这里写需要循环执行的代码
}
}
}
线程同步
解决数据共享问题, 必须使用同步, 所谓同步就是指多个线程在同一时间段内只能有一个线程执行指定代码, 其他线程要等待线程完成之后才可以继续执行
使用关键字: synchronized ()
含义: 同步代码块中的内容只有一个线程可以进入
注意: 同步关键字里面的对象必须是同一个对象
同步的例子:
生产者与消费者模型: 生产者与消费者
卖票
package org.lulu.learn;
/**
* Project: Day09
* Created: Lulu
* Date: 2016/8/6
*/
public class Sell extends Thread {
private static int ticket = 100;
private static Object object = new Object();
@Override
public void run() {
super.run();
while (true) {
//线程锁
/*
含义: 同步代码块中的内容只有一个线程可以进入
注意: 里面的对象必须是同一个对象
*/
synchronized (object){
if (ticket <= 0) {
break;
}
// if (sell()){
// break;
// }
//买票的耗时操作
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "Ticket : " + ticket--);
}
}
}
//同步方法的锁对象时当前对象(只能是静态方法, 锁得是Sell.class; 非静态是this)
private static synchronized boolean sell(){
if (ticket <= 0) {
return true;
}
//买票的耗时操作
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "Ticket : " + ticket--);
return false;
}
}
临界资源:
多个线程访问同一个资源, 该资源就称之为临界资源
Thread sleep方法
在休眠时间内是不参与CPU的抢夺的, 不会让出锁
如果正在休眠的线程被打断, 就会抛出InterruptedException异常
“醒来”后再次参与CPU时间片的抢夺
Object wait方法
表示当前线程进入等待状态, 会让出CPU并释放该监视器上的锁
API说: 在其他的线程调用此对象额notify()方法或notifyAll()方法, 或者其他某个线程中断了当前线程, 或者已超过某个实际时间量前, 导致当前线程等待.
notify中如果唤醒两个线程中wait, 会先唤醒先wait的线程, 在此情况下, 写两个notify()会唤醒两个wait的线程
object.notifyAll();//唤醒所有, 但是不一定先唤醒哪一个
Java程序什么时候结束?
除了用System.exit(0)退出整个虚拟机和人为干预结束以外, 如果进程中只有守护线程的时候进程结束!
Cpu在同一个时间点只会执行一个动作
CPU的频率: 1S 之内做1+1的次数