进程、线程、多线程
一个进程可以包括多个线程,但是至少需要包含一个线程
线程是CPU执行的最小单位
对于单核CPU而言,一次只能执行一个线程
但是由于不同线程间切换速度极快,近似达到了同步执行的效果
线程创建
创建Java的子线程有两种方法
1--继承Thread类
2--实现Runnable接口
3--实现callable接口(了解即可)
建议使用方法2,自定义类实现Runnable接口后便于被多个线程使用
继承Thread类
STEP1:自定义类,继承Thread
STEP2:重写run方法,真正需要执行的程序放在run方法里
STEP3:创建STEP1中的自定义类,调用start方法,运行线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class Main{ public static void main(String[] args) { new MyThread().start(); for(int i = 0 ; i < 20 ; i ++){ System.out.println("In main process:"+i); } } }
class MyThread extends Thread{ @Override public void run(){ for(int i = 0 ; i < 20 ; i ++){ System.out.println("In Thread processs:" + i); } } }
|
实现Runnable接口
STEP1:自定义类,实现runnable接口
STEP2:实现接口中的run方法,真正需要执行的程序放在run方法里
STEP3:使用STEP1中的自定义类来实例化Thread类,调用start方法,运行线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Main{ public static void main(String[] args) { new Thread(new MyRunnable()).start(); for(int i = 0 ; i < 20 ; i ++){ System.out.println("In main process"+i); } } }
class MyRunnable implements Runnable{ public void run(){ for(int i = 0 ; i < 20 ; i ++){ System.out.println("In Thread processs:" + i); } } }
|
实现Callable接口
多线程08:实现Callable接口_哔哩哔哩_bilibili
线程停止
JDK中提供的stop、destroy方法目前已经被废弃
目前主流的做法是设置一个变量,来控制线程的运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class Main{ public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); new Thread(myRunnable,"The thread").start(); try{ Thread.sleep(3); }catch(InterruptedException e){ e.printStackTrace(); } myRunnable.stop(); } }
class MyRunnable implements Runnable{ private boolean alive = true; public void run(){ while(alive){ System.out.println(Thread.currentThread().getName() + " is running..."); } } public void stop(){ alive = false; } }
|
线程休眠
每一个对象都有一把锁,sleep不会释放锁
使用Sleep实现简单的计时器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class Main{ public static void main(String[] args) { new Thread(new Clock(),"ClockCounter").start(); } } class Clock implements Runnable{ public void run(){ int cnt = 1; while(cnt < 10){ try{ Thread.sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } System.out.println("The Clock count => " + cnt); cnt++; } } }
|
线程礼让
礼让线程,就是让一个进程从运行状态重新变为就绪状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class Main{ public static void main(String[] args) { new Thread(new MyRunnable(),"a").start(); new Thread(new MyRunnable(),"b").start(); } } class MyRunnable implements Runnable{ public void run(){ System.out.println(Thread.currentThread().getName() + "开始执行"); Thread.yield(); System.out.println(Thread.currentThread().getName() + "结束执行"); } }
|
线程强制执行
join方法可以被理解成线程间的“插队”
调用该方法可以使得其他线程进入阻塞状态,优先执行某个线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public class Main{ public static void main(String[] args) throws InterruptedException{ Thread thread = new Thread(new MyRunnable()); thread.start(); for(int i = 1 ; i <= 100 ; i ++){ System.out.println("Normal => " + i); if(i == 10){ thread.join(); } } } } class MyRunnable implements Runnable{ public void run(){ for(int i = 1 ; i <= 20 ; i ++){ System.out.println("VIP => "+i); } } }
|
线程优先级
线程优先级只能保证高优先级的线程优先被调用
但并不是一个严格保证,低优先级的线程仍有可能被提前调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Main{ public static void main(String[] args) throws InterruptedException{ Thread t1 = new Thread(new MyRunnable(),"t1"); t1.setPriority(1); Thread t2 = new Thread(new MyRunnable(),"t1"); t2.setPriority(2); Thread t3 = new Thread(new MyRunnable(),"t1"); t3.setPriority(3); t1.start();t2.start();t3.start(); } } class MyRunnable implements Runnable{ public void run(){ System.out.println(Thread.currentThread().getName() + "is running:" + Thread.currentThread().getPriority()); } }
|
守护线程
线程包括守护线程和用户线程
虚拟机运行在所有用户线程结束后即结束,不需要等待守护线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class Main{ public static void main(String[] args) throws InterruptedException{ Thread god = new Thread(new God()); god.setDaemon(true); Thread you = new Thread(new You()); you.setDaemon(false); god.start(); you.start(); } } class God implements Runnable{ public void run(){ while(true){ System.out.println("God bless you"); } } } class You implements Runnable{ public void run(){ for (int i = 0; i < 36500; i++) { System.out.println("I am alive today"); } System.out.println("-----Goodbye world-----"); } }
|
线程同步
例1:售票机卖票问题
三个售票机同时售票,两个售票机可能卖出同一张票,
原因是:因为一个售票机卖出票x时,另一个售票机不会等待其操作结束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class Main{ public static void main(String[] args) { new Thread(new SellTicket(),"SellMachine_1").start(); new Thread(new SellTicket(),"SellMachine_2").start(); new Thread(new SellTicket(),"SellMachine_3").start(); } } class SellTicket implements Runnable{ static int ticketNum = 1000; public void run(){ while (ticketNum >= 1){ try{ Thread.sleep(10); }catch(InterruptedException e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " has selled ticket_" + (ticketNum--)); } } }
|
解决方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class Main{ public static void main(String[] args) { SellTicket sellTicket = new SellTicket(); new Thread(sellTicket,"SellMachine_1").start(); new Thread(sellTicket,"SellMachine_2").start(); new Thread(sellTicket,"SellMachine_3").start(); } } class SellTicket implements Runnable{ static int ticketNum = 1000; private boolean flag = true; public void run(){ System.out.println(Thread.currentThread().getName() + " start"); while (flag){ buy(); } } public synchronized void buy(){ if(ticketNum >= 1){ System.out.println(Thread.currentThread().getName() + " has selled ticket_" + (ticketNum--)); }else{ flag = false; } } }
|
例2:银行取钱问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| public class Main { public static void main(String[] args) { Account myBankAccount = new Account(100,"Peter's account"); new Drawing(myBankAccount,50,"Peter").start(); new Drawing(myBankAccount,100,"girlfriend").start(); } }
class Account{ private int money; private String name;
public Account(int money_,String name_){ this.money = money_; this.name = name_; }
public int getMoney(){ return money; } public void setMoney(int nowMoney){ money = nowMoney; } public String getName(){ return name; } }
class Drawing extends Thread{ Account account; int drawingMoney; String name;
public Drawing(Account account,int drawingMoney,String name){ this.account = account; this.drawingMoney = drawingMoney; this.name = name; }
@Override public void run() { if(account.getMoney() < drawingMoney){ System.out.println("操作人 => " + name); System.out.println("错误 => 余额不足"); System.out.println("-------------"); return; } account.setMoney(account.getMoney() - drawingMoney); System.out.println("操作人 => " + name); System.out.println("已成功取出 => " + drawingMoney); System.out.println("账户余额 => " + account.getMoney()); System.out.println("-------------"); } }
|
解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Drawing extends Thread{ Account account; int drawingMoney; String name;
public Drawing(Account account,int drawingMoney,String name){ this.account = account; this.drawingMoney = drawingMoney; this.name = name; }
@Override public void run() { synchronized (account){ if(account.getMoney() < drawingMoney){ System.out.println("操作人 => " + name); System.out.println("错误 => 余额不足"); System.out.println("-------------"); return; } account.setMoney(account.getMoney() - drawingMoney); System.out.println("操作人 => " + name); System.out.println("已成功取出 => " + drawingMoney); System.out.println("账户余额 => " + account.getMoney()); System.out.println("-------------"); } } }
|