JavaEE 多线程
java中的CPU调度使用的是抢占式调度,然后的话,可以通过setPriority设置优先级,优先级越高,越可能抢到CPU,主打随机性。守护线程,如果非守护线程还没有结束,那么大家都正常运行,如果非守护线程都结束了,那么就会陆续结束守护线程。使用sleep方法进行线程的休眠,哪个线程执行到了这个方法,那么就进行休眠,单位为ms。多线程中的不安全性(线程在执行的过程中随时可能会失去CPU的执行权)线
-
多线程
多线程是为了提高资源利用率,在‘同一个程序(进程)’内部,并发执行多个‘任务(代码路径)’的技术。
并发: 同一时刻,多个指令在单个CPU上交替执行
并行: 同一时刻,多个CPU同时执行多个指令
-
多线程的实现方式:
通过继承Thread,重写run方法来实现
public static void main(String[] args) { MyThread myThread=new MyThread(); MyThread myThread1=new MyThread(); myThread1.setName("Rance1"); myThread.setName("Rance2"); myThread1.start(); myThread.start(); } static class MyThread extends Thread{ @Override public void run(){ String name=getName(); for (int i = 0; i < 100; i++) { System.out.println(name+": RanceXXX"); //出让线程,表示让出当前CPU的执行权 Thread.yield(); } } } - 通过实现Runnable接口,重写run方法来实现

- 为了获取到线程的返回值,通过实现Callable接口,重写call方法,用FutureTask来管理线程的返回值
public static void main(String[] args) throws ExecutionException, InterruptedException { //创建MyCallable对象 MyCallable mc=new MyCallable(); //创建Future实现类FutureTask来管理MyCallable的结果 FutureTask<Integer> ft=new FutureTask<>(mc); //创建线程,传入ft参数 Thread thread=new Thread(ft); thread.start(); Integer i = ft.get(); System.out.println(i); //插入线程,使thread线程运行在main线程(当前线程)的前面 t.join(); fori.10.sout.... } public class MyCallable implements Callable<Integer> {//泛型为返回值类型 @Override public Integer call() throws Exception { int sum=0; for (int i = 1; i <= 100; i++) { sum = i + sum; } return sum; } }
-
Thread常见的成员方法:

-
main线程负责main方法中的代码的执行
使用sleep方法进行线程的休眠,哪个线程执行到了这个方法,那么就进行休眠,单位为ms
java中的CPU调度使用的是抢占式调度,然后的话,可以通过setPriority设置优先级,优先级越高,越可能抢到CPU,主打随机性
-
守护线程,如果非守护线程还没有结束,那么大家都正常运行,如果非守护线程都结束了,那么就会陆续结束守护线程

-
<<时间之外的往事(计算机操作系统的事情)>> 1.


-
多线程中的不安全性(线程在执行的过程中随时可能会失去CPU的执行权)
- 重复票是怎么回事
- 票超出了是怎么回事

-
使用同步代码块解决多线程不安全的问题:
public class MyThread extends Thread { public static int ticket = 0; @Override public void run() { while (true) {//同步synchronized一定要写在while里面,然后锁一定要是唯一的一个对象,MyThread.class表示的是MyThread的字节码文件 synchronized (MyThread.class) { if (ticket < 100) { System.out.println(getName() + ":正在卖第" + ticket + "张票"); ticket++; } else { break; } } } } } -
同步方法,在方法前加入synchronized关键字
@Override public void run() { while (true) { if (extracted()) break; } } private synchronized boolean extracted() { if (ticket < 100) { System.out.println(getName() + ":正在卖第" + ticket + "张票"); ticket++; } else { return true; } return false; } -
Lock手动上锁开锁的操作:
public class MyThread extends Thread { public static int ticket = 0; static Lock lock=new ReentrantLock(); @Override public void run() { while (true) { lock.lock(); try { if (ticket < 100) { System.out.println(getName() + ":正在卖第" + ticket + "张票"); ticket++; } else { break; } } catch (Exception e) { throw new RuntimeException(e); } finally { lock.unlock(); } } } } -
死锁,锁的嵌套:

-
<<时间之外的往事(操作系统相关之pv操作)>>
- 生产者和消费者模型

b.生产者和消费者模型的代码实现:

- 生产者和消费者模型
-
阻塞队列实现生产者消费者模型
public class Cook extends Thread{ ArrayBlockingQueue<String> arrayBlockingQueue; public Cook(ArrayBlockingQueue<String> arrayBlockingQueue) { this.arrayBlockingQueue = arrayBlockingQueue; } @Override public void run(){ while(true){ try { arrayBlockingQueue.put("面条"); System.out.println("厨师做了一碗面"); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } -
抢红包的逻辑:
public class People extends Thread { static double redEnvelope = 100; static int count = 3; static final double MIN=0.01; @Override public void run() { synchronized (People.class) { if(count==0){ System.out.println(Thread.currentThread().getName()+"没抢到红包!!!"); }else{ Random r=new Random(); //用来表示中奖金额 double prize=0; if(count==1){ prize=redEnvelope; } else{ double ram=redEnvelope-(count-1)*MIN; prize = ((prize = r.nextDouble(ram)) < MIN) ? MIN: prize; } System.out.println(Thread.currentThread().getName()+"抢到了"+prize+"元红包!!!"); redEnvelope-=prize; count--; } } } } -
抽奖箱逻辑:
public class LotteryPool extends Thread{ static ArrayList<Integer> list=new ArrayList<>(); static { Collections.addAll(list,10,2,5,20,100,50,200,500,800,80,300,700); } @Override public void run(){ while(true){ synchronized (LotteryPool.class){ if(list.isEmpty()){ break; } else{ Collections.shuffle(list); Integer remove = list.removeFirst(); System.out.println(Thread.currentThread().getName()+"又产生了一个"+remove+"元大奖"); } } try { Thread.sleep(5000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } -
线程栈是不唯一的,每个线程有自己的栈,堆内存是唯一的
- 这个图表示main线程栈读取main方法,main方法进栈,然后,创建了两个线程对象,在堆中开辟内存空间,然后当执行start方法时,就会开启线程1和线程2自己的栈,run方法进栈.

- 这个图表示main线程栈读取main方法,main方法进栈,然后,创建了两个线程对象,在堆中开辟内存空间,然后当执行start方法时,就会开启线程1和线程2自己的栈,run方法进栈.
-
抽奖箱最终版:
public class LotteryPool implements Callable<Integer> { static ArrayList<Integer> list=new ArrayList<>(); static { Collections.addAll(list,10,2,5,20,100,50,200,500,800,80,300,700); } @Override public Integer call() throws Exception { ArrayList<Integer> boxList=new ArrayList<>(); while(true){ synchronized (LotteryPool.class){ if(list.isEmpty()){ System.out.println(Thread.currentThread().getName()+" "+boxList); break; } else{ Collections.shuffle(list); Integer remove = list.removeFirst(); boxList.add(remove); } } Thread.sleep(10); } if(boxList.isEmpty()) return null; else return Collections.max(boxList); } } public class Test { public static void main(String[] args) throws ExecutionException, InterruptedException { LotteryPool lotteryPool=new LotteryPool(); FutureTask<Integer> ft1=new FutureTask<>(lotteryPool); FutureTask<Integer> ft2=new FutureTask<>(lotteryPool); Thread t1=new Thread(ft1); Thread t2=new Thread(ft2); t1.setName("线程1"); t2.setName("线程2"); t1.start(); t2.start(); Integer i1 = ft1.get(); Integer i2 = ft2.get(); System.out.println(i1+" "+i2); } } -
线程池
-
原理:

-
代码实现:
public class Test { public static void main(String[] args) { // ExecutorService pool = Executors.newCachedThreadPool(); MyRunnable myRunnable=new MyRunnable(); // pool.submit(myRunnable); ExecutorService executorService = Executors.newFixedThreadPool(3); executorService.submit(myRunnable); executorService.submit(myRunnable); executorService.submit(myRunnable); executorService.submit(myRunnable); executorService.submit(myRunnable); } }
-
-
自定义线程池:
- 来了8个任务,线程池先创建3个核心线程来完成三个任务,然后长度为3,把任务4,5,6进入阻塞队列排队,任务7和8使用临时线程来进行操作

- 来了8个任务,线程池先创建3个核心线程来完成三个任务,然后长度为3,把任务4,5,6进入阻塞队列排队,任务7和8使用临时线程来进行操作
new ThreadPoolExecutor(
3,//核心线程数量
6,//总线程数量
60,//空闲清理线程时间
TimeUnit.SECONDS,//清理时间的单位
new ArrayBlockingQueue<>(3),//排队的队伍长度
Executors.defaultThreadFactory(),//线程从哪里来
new ThreadPoolExecutor.AbortPolicy()
);
更多推荐


所有评论(0)