1.什么是进程、线程
进程可以简单的理解为应用程序。多线程,相当于多个人共同完成一件事情,每个线程,独立完成一件任务。因此,一个进程至少有一个线程,一个线程不能独立存在,它必须是进程的一部分。
进程:每个独立运行着的程序。具有独立的内存空间和系统资源。(建大厦)
线程:是一个进程内部的一条执行路径。是系统独立调度和分配CPU的最小单位。(搬砖头)
2.创建线程的方式(三种)
- 1.通过实现 Runnable 接口;(存在共享资源时使用——是否是相同操作)
- 2.通过继承 Thread 类本身;(没有共享资源时可用)
- 3.通过 Callable 和 Future 创建线程。(JDK1.5开始引入)
对比:
-
1. 采用实现 Runnable、Callable 接口的方式创建多线程时,线程类只是实现了 Runnable 接口或 Callable 接口,还可以继承其他类。
-
2. 使用继承 Thread 类的方式创建多线程时,编写简单,如果需要访问当前线程,则无需使用 Thread.currentThread() 方法,直接使用 this 即可获得当前线程。
3.线程的状态及特性
线程具有随机性:谁能抢到CPU,谁执行。
package com.test; public class ThreadDemo1 { public static void main(String[] args) { // TODO Auto-generated method stub MyThread myThread=new MyThread("name"); //myThread.run();//主线程 myThread.start();//多线程 }}class MyThread extends Thread{ public MyThread() { super(); // TODO Auto-generated constructor stub } public MyThread(String name) { super(name); } public void run() { for(int i=0;i<20;i++) { System.out.println(Thread.currentThread().getName()+"→"+i); } }}
创建线程,输出1~100之间的偶数。要求使用线程实现,继承Thread类
package com.test;public class ThreadDemo2 { public static void main(String[] args) { // TODO Auto-generated method stub OutputEven outputEven=new OutputEven(); outputEven.start(); }}class OutputEven extends Thread{ @Override public void run() { // TODO Auto-generated method stub for(int i=1;i<=100;i++) { if(i%2==0) { System.out.println(Thread.currentThread().getName()+"→"+i); } } } }
使用线程模拟四个工人搬砖场景,谁抢到托运机谁去搬砖
package com.test;public class ThreadDemo3 { public static void main(String[] args) { // TODO Auto-generated method stub Worker worker1=new Worker("张三1","搬砖"); Worker worker2=new Worker("张三2","搬砖"); Worker worker3=new Worker("张三3","搬砖"); Worker worker4=new Worker("张三4","搬砖"); worker1.start(); worker2.start(); worker3.start(); worker4.start(); }}class Worker extends Thread{ String name; String task; public Worker() { // TODO Auto-generated constructor stub super(); } public Worker(String name, String task) { super(); this.name = name; this.task = task; } @Override public void run() { // TODO Auto-generated method stub work(); } public void work() { System.out.println(name+"正在"+task); }}
三个窗口都可以卖100张票。
package com.test;public class ThreadDemo4 { public static void main(String[] args) { // TODO Auto-generated method stub WinTicket winTicket1=new WinTicket("窗口1"); WinTicket winTicket2=new WinTicket("窗口2"); WinTicket winTicket3=new WinTicket("窗口3"); winTicket1.start(); winTicket2.start(); winTicket3.start(); }}class WinTicket extends Thread{ private int ticket=100; public WinTicket() { super(); // TODO Auto-generated constructor stub } public WinTicket(String name) { super(name); } @Override public void run() { // TODO Auto-generated method stub while(true) { if(ticket>0) { String name=Thread.currentThread().getName(); System.out.println(name+"卖出"+ticket--); }else { break; } } } }
4.多个线程共享资源
三个窗口共同卖100张票。
package com.test;public class ThreadDemo5 { public static void main(String[] args) { // TODO Auto-generated method stub //创建共享资源对象 TicketRes ticketRes=new TicketRes(); //创建线程对象 Thread w1=new Thread(ticketRes,"窗口1"); Thread w2=new Thread(ticketRes,"窗口2"); Thread w3=new Thread(ticketRes,"窗口3"); w1.start(); w2.start(); w3.start(); }}//共享资源类class TicketRes implements Runnable{ private int ticket=100; @Override public void run() { // TODO Auto-generated method stub while(true) { if(ticket>=1) { System.out.println(Thread.currentThread().getName()+"卖第"+ticket+"张票"); ticket--; }else { break; } } }}//出现一个问题:第一百张票会同时在三个窗口卖出。这个涉及到同步和异步的问题?该怎么解决呢?揭晓答案
5.线程调度
优先级
优先级用1-10表示,1的优先级最低,10的优先级最高,默认情况为5
setPriority(int grade);
调度方法
join():阻塞指定的线程等到另一个线程完成以后再执行
package com.test;public class JoinDemo { public static void main(String[] args) throws InterruptedException { // TODO Auto-generated method stub System.out.println("主线程在执行..."); JoinThread joinThread1=new JoinThread("线程1"); JoinThread joinThread2=new JoinThread("线程2"); JoinThread joinThread3=new JoinThread("线程3"); System.out.println("启动子线程..."); joinThread1.start(); joinThread2.start(); joinThread3.start(); joinThread1.join(); joinThread2.join(); joinThread3.join(); for(int i=0;i<10;i++) { System.out.println("主线程正在执行..."); } System.out.println("结束"); } }class JoinThread extends Thread{ public JoinThread() { super(); // TODO Auto-generated constructor stub } public JoinThread(String name) { super(name); // TODO Auto-generated constructor stub } @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<10;i++) { System.out.println(Thread.currentThread().getName()+"→"+i); } } }
sleep():会暂时释放CPU, 让给其他线程执行, 即使没有其他线程抢占CPU,也需要等待睡眠时间到了以后才能真正的指定
package com.test;public class SleepDemo { public static void main(String[] args){ // TODO Auto-generated method stub SleepThread sleepThread=new SleepThread(); sleepThread.start(); }}class SleepThread extends Thread{ public SleepThread() { super(); // TODO Auto-generated constructor stub } public SleepThread(String name) { super(name); // TODO Auto-generated constructor stub } @Override public void run() { // TODO Auto-generated method stub for(int i=10;i>=0;i--) { try { Thread.sleep(1000); System.out.println(i); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
yield():执行的时候会让出CPU , 但是会立马同其他的线程抢占CPU
package com.test;public class YieldDemo { public static void main(String[] args) { // TODO Auto-generated method stub YieldThread yieldThread1=new YieldThread("线程1"); YieldThread yieldThread2=new YieldThread("线程2"); yieldThread1.start(); yieldThread2.start(); }}class YieldThread extends Thread{ public YieldThread() { super(); // TODO Auto-generated constructor stub } public YieldThread(String name) { super(name); // TODO Auto-generated constructor stub } @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<20;i++) { System.out.println(Thread.currentThread().getName()+"→"+i); Thread.yield();//避让,谦让,让出CPU,还有再去抢的资格 } } }