进程:程序的一次动态加载过程,包括了代码加载,编译,执行,结束的一个完整过程
线程:线程是比进程更小的单位,行为很像进程,一个进程在执行过程中可以产生多个线程
多线程序机制:每个java程序都有一个主线程,当jvm加载代码,发现main方法,此时就会启动主线程,在mian方法执行过程中再创建的线程就是其他线程。
线程的四种状态:
新建状态:Thread类被创建
运行状态:执行run()方法
中断状态:
- 1.资源从当前线程被切换给了其他线程
- 2.调用sleep()方法
- 3.wait()方法
- 4 .线程执行某个操作期间进入了阻塞状态
死亡状态:1.正常运行完全部工作 2.被强制中断
状态图:
java线程的优先级在常数1-10之间,默认为5级
创建线程的三种方法:
1.线程任务类,接口Runnable
public class ThreadB implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++) {
System.out.println(i+"B线程");
}
}
}
启动线程时,需要通过Thread 对象进行启动
public class ThreadTestB {
public static void main(String[] args) {
//1.创建线程任务
ThreadB tb=new ThreadB();
//2.通过线程任务,创建线程对象
Thread t=new Thread(tb);
t.start();
for(int i=0;i<10;i++) {
System.out.println(i+"Main线程");
}
}
}
2.继承Thread的线程类
public class ThreadTestA {
public static void main(String[] args) {
//1.创建线程对象
ThreadA ta=new ThreadA();
ta.start();
for(int i=0;i<10;i++) {
System.out.println(i+"Main线程");
}
}
}
启动线程时,直接 new 线程对象.start()方法
public class ThreadA extends Thread{
@Override
public void run() {
for(int i=0;i<10;i++) {
System.out.println(i+"A线程");
}
}
}
线程同步(synchronized)
问题:当两个或多个线程同时访问同一变量时,并且对该变量会进行修改,那么就可能会出现混乱
线程同步方法:使用 synchronized 修饰来方法
线程同步机制:当一个线程A使用synchronized方法时,其他线程想用synchronized方法时就必须等待,直到线程A使用完synchronized方法。
例子:会计和出纳共同拥有一个账本,他们都可以使用saveOrTake方法对账本进行访问。如果会计正在使用saveOrTake存入钱时,出纳被禁止使用,反之如此。
package com.money;
//线程同步(synchronized):
public class Test {
public static void main(String[] args) {
Bank bank = new Bank();
bank.setMoney(300);
Thread accountant = new Thread(bank); //声明线程变量会计
Thread cashier = new Thread(bank); //声明线程变量出纳
accountant.setName("accountant");
cashier.setName("cashier");
accountant.start();
cashier.start();
}
}
package com.money;
public class Bank implements Runnable {
int money = 200;
public void setMoney(int n) {
money = n;
}
public void run() {
if(Thread.currentThread().getName().equals("accountant")) {
saveOrTake(300);
}else if(Thread.currentThread().getName().equals("cashier")) {
saveOrTake(150);
}
}
//存取方法 (如果将synchronized取掉,线程就不会有等待,结果将会不一样)
public synchronized void saveOrTake(int amount) {
if(Thread.currentThread().getName().equals("accountant")) {
for(int i=1;i<=3;i++) {
money=money+amount/3; //每次存入100,暂停一下
System.out.println(Thread.currentThread().getName()+
"存入"+amount/3+"元,账上有"+money+"元");
}
try {
Thread.sleep(1000); //此时出纳无法使用saveOrTake方法
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else if(Thread.currentThread().getName().equals("cashier")) {
for(int i=1;i<=3;i++) {
money=money-amount/3; //每次取出50,暂停一下
System.out.println(Thread.currentThread().getName()+
"取出"+amount/3+"元,账上有"+money+"元");
}
try {
Thread.sleep(1000); //此时会计无法使用saveOrTake方法
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
协调同步的线程(wait)
问题:当一个线程使用同步方法后,其他线程就必须等待,直到当前线程使用完该方法。同步方法特殊情况。
方法:当一个线程中在使用的同步方法时,需要用到其中的某个变量,而此变量又需要其他线程修改后才符合此线程的需要,此时就需要用wait()方法。
wait()方法:中断线程的执行,使当前线程等待,允许其他线程使用这个同步方法。使用完后通过线程结束等待:notify(),notifyall()
例子:A和B买电影票,电影票5元一张,售票员只有两张5元的钱,A有20元排第一位,B有5元排第二位。因此A必须等待B先买票。
package com.ticket;
public class Test {
public static void main(String[] args) {
Ticket ticket = new Ticket();
Thread A = new Thread(ticket);
Thread B = new Thread(ticket);
A.setName("A");
B.setName("B");
A.start();
B.start();
}
}
package com.ticket;
public class Ticket implements Runnable {
int five=2;
int twenty=0;
@Override
public void run() {
if(Thread.currentThread().getName().equals("A")) {
saleTicket(20);
}else if(Thread.currentThread().getName().equals("B")) {
saleTicket(5);
}
}
public synchronized void saleTicket(int money) {
if(money==5) {
five=five+1;
System.out.println(Thread.currentThread().getName()+"拿到入场票");
}else if(money==20) {
while(five<3) { //如果5元少于3张则需要等待
try {
System.out.println(Thread.currentThread().getName()+"等待买票");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
five=five-3;
twenty=twenty+1;
System.out.println(Thread.currentThread().getName()+"拿到入场票,收到15元找零");
}
notifyAll();
}
}