Java多线程随笔
什么是进程?
系统进行资源分配和调度的基本单位。
什么是线程?
cpu调度的最小单位。
什么是多线程?
允许多个线程在同一个程序中并发执行。
多线程作用?
提高程序执行效率。
多线程实现的三种方式
1.通过继承Thread类,重写run()方法实现
public class ThreadDemo {public static void main(String args[]){MyThread myThread1 = new MyThread();myThread1.setName("Thread-1");MyThread myThread2 = new MyThread();myThread2.setName("Thread-2");myThread1.start();myThread2.start();}
}
class MyThread extends Thread{public void say(){for(int i=0;i<100;i++){System.out.println(getName()+": "+i);}}public void run(){say();}
}
可通过getName()获取当前线程名。
2.通过实现Runnable接口,再创建Thread类执行其run()方法。
public class RunnableDemo {public static void main(String[] args) {People people1 = new People();People people2 = new People();Thread thread1 = new Thread(people1);Thread thread2 = new Thread(people2);thread1.setName("people1");thread2.setName("people2");thread1.start();thread2.start();}
}
class People implements Runnable{private void say(){for(int i=0;i<100;i++){System.out.println(Thread.currentThread().getName() + " say hello"+i);}}public void run() {say();}
}
因为没有继承Thread类,所以不能直接调用getName(),
而是通过获取当前执行程序的线程Thread.currentThread(),再获取线程名。
3.通过Callable接口和Future接口实现
Callable泛型为结果的类型,即call方法返回类型。
import java.util.concurrent.Callable;public class MyCallable implements Callable<Integer> {public Integer call() throws Exception {return 10;}
}
创建FutureTask对象中泛型也为返回值类型,通过Thread代理执行后,通过get()方法获取返回结果
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class CallableDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {MyCallable mc = new MyCallable();FutureTask<Integer> ft = new FutureTask<>(mc);new Thread(ft).start();System.out.println(ft.get());}
}
什么是守护线程?
所有非守护线程执行完成后,守护线程即使未执行完成,也会结束。
场景
比如一个聊天框,现在正在传输文件,聊天框是一个线程,传输文件是一个线程,当关闭聊天框后,传输文件线程也会关闭。
同步代码块
synchronized 同步代码块中代码是轮流执行,执行中加锁,其他线程无法进入。
锁对象唯一,一般是该类的字节码文件(xx.class)
lock锁
类似同步代码块
lock.lock()上锁。
lock.unlock()解锁。
建议将解锁放在finally代码块中,防止中间代码break等跳过解锁。
package lockpackage;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class MyThread implements Runnable{int count =0;Lock lock = new ReentrantLock();@Overridepublic void run() {while(true){lock.lock();try{if(count == 100) break;count++;Thread.sleep(10);System.out.println(Thread.currentThread().getName()+"正在售卖第"+count+"张票");}catch( InterruptedException e){e.printStackTrace();}finally {lock.unlock();}}}
}
等待和唤醒
wait():线程等待,直到其他线程唤醒
notify():随机唤醒线程
notifyAll():唤醒所有等待线程
案例
package threadDemo;public class Cook implements Runnable{@Overridepublic void run() {while(true){if(Desk.count == 0){break;}else{synchronized (Desk.lock){if(Desk.eatFlag == 1){try {Desk.lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}else{System.out.println("厨师正在制作食物。。。");Desk.eatFlag = 1;Desk.lock.notifyAll();}}}}}
}
package threadDemo;public class Customer implements Runnable {@Overridepublic void run() {while (true){if(Desk.count == 0){break;}else{synchronized (Desk.lock){if(Desk.eatFlag == 0){try {Desk.lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}else{Desk.count--;Desk.eatFlag = 0;System.out.println("顾客还能吃第"+Desk.count+"碗面条");Desk.lock.notifyAll();}}}}}
}
package threadDemo;public class Desk {//能吃多少碗饭public static int count = 10;//锁对象public static Object lock = new Object();//吃的状态 0:未吃 1:已吃public static int eatFlag = 0;
}
package threadDemo;public class Main {public static void main(String[] args) {Cook cook = new Cook();Customer customer = new Customer();new Thread(cook).start();new Thread(customer).start();}
}
ArrayBlockingQueue
阻塞队列
put:放入数据(如果队列放满了等待)
take:取出数据(两方法都加了锁)(如果数据队列为空则等待)ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(1);//队列长度
线程池
ExecutorService executorService = Executors.newFixedThreadPool(3);//创建线程数为3的线程池
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();//线程池数无上限executorService.submit(执行任务);//调用该对象run方法
executorService.shutdown(); //关闭线程池//七大核心public class Main {public static void main(String[] args) {ThreadPoolExecutor executor = new ThreadPoolExecutor(3, //核心线程数5, //最大线程数60, //临时线程存活时间TimeUnit.SECONDS, //时间单位new ArrayBlockingQueue<>(2), //阻塞队列Executors.defaultThreadFactory(), //线程工厂new ThreadPoolExecutor.AbortPolicy() //线程池饱和策略);executor.submit(); //提交任务}
}