当前位置: 首页> 游戏> 手游 > 望野博物馆阎焰简历_重庆本地生活平台_seo实战优化_站长之家网站排行榜

望野博物馆阎焰简历_重庆本地生活平台_seo实战优化_站长之家网站排行榜

时间:2025/7/11 15:51:49来源:https://blog.csdn.net/lanssssss/article/details/146988691 浏览次数:2次
望野博物馆阎焰简历_重庆本地生活平台_seo实战优化_站长之家网站排行榜

基础知识

线程

线程是操作系统能够进行运算调度的最小单位.它被包含到进程中,是进程中的实际运作单位.

多线程用来提高效率.让程序同时做多件事.

并发

在同一时刻,有多个指令在单个CPU上交替执行.

并行

在同一时刻,有多个指令在多个CPU上同时执行

多线程实现方式

1.实现runnable接口

2.继承Thread类,重写run方法.

3.实现Callable接口

package com.lanqiao.study;import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;/*** @author: lans* @date: 2025/4/1* @name: 刘宇*/
public class ThreadDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {/*** 多线程的第三种实现方式* 1.创建一个类MyCallable实现Callable接口* 2.重写call(有返回值,表示多线程运行的结果)* 3.创建MyCallable对象(表示多线程要执行的任务)* 4.创建FutureTask的对象(作用管理多线程运行的结果)* 5.创建Thread类的对象,并启动(表示线程)*///3.创建MyCallable对象(表示多线程要执行的任务)MyCallable mc = new MyCallable();//4.创建FutureTask的对象(作用管理多线程运行的结果)FutureTask<Integer> ft = new FutureTask<>(mc);//创建线程对象Thread t1 = new Thread(ft);t1.start();//获取多线程运行的结果Integer result = ft.get();System.out.println(result);}
}

常见的成员方法

package com.lanqiao.study;/*** @author: lans* @date: 2025/4/1* @name: 刘宇*/
public class ThreadDemo1 {public static void main(String[] args) {//1.String getName()返回该线程名字//2.void setName(String name)设置线程的名字//要设置名字 可以用set方法设置 也可以构造方法设置//3.static Thread currentThread()获取当前线程的对象//细节:当JVM启动后 会自动启动多条线程//其中有一条main线程 它的作用是去调用Main方法 并执行里面的代码//在以前 我们写的所有代码 起始都是运行在Main线程当中的//4.static void sleep(long time)让线程休眠指定的时间,单位为ms// 哪条线程执行到这个方法 就会停留对应时间,时间到后自动醒来 自动执行其他代码MyThread t1 = new MyThread();MyThread t2 = new MyThread("飞机");t1.start();t2.start();}
}
package com.lanqiao.study;/*** @author: lans* @date: 2025/4/1* @name: 刘宇*/
public class MyThread extends Thread {@Overridepublic void run() {for(int i=0;i<100;i++){try{Thread.sleep(1000);}catch(Exception e){e.printStackTrace();}System.out.println(getName()+"@"+i);}}public MyThread(String name) {super(name);}public MyThread() {}
}

线程的优先级

JAVA属于抢占式调度 充满随机性

优先级分为10档 最小1 最大10 默认5

优先级不是绝对的 只是一个概率

package com.lanqiao.study;/*** @author: lans* @date: 2025/4/1* @name: 刘宇*/
public class ThreadDemo2 {public static void main(String[] args) {/*setPriority(int newPriority) 设置线程的优先级final int getPriority()     获取线程的优先级*/MyRuunable mr = new MyRuunable();Thread t1 = new Thread(mr,"飞机");Thread t2 = new Thread(mr,"坦克");t1.setPriority(1);t2.setPriority(9);
//        System.out.println(t1.getPriority());
//        System.out.println(t2.getPriority());t1.start();t2.start();}
}
package com.lanqiao.study;/*** @author: lans* @date: 2025/4/1* @name: 刘宇*/
public class MyRuunable implements Runnable {@Overridepublic void run() {for(int i=1;i<=100;i++){System.out.println(Thread.currentThread().getName()+":"+i);}}
}

守护线程

final void setDaemon(boolean on)

当其他的非守护线程执行完毕后,守护线程会陆续结束

可以用于这样的场景 聊天:线程1 传输文件:线程2

聊天结束了传输文件就不必要了(特殊情境)

礼让线程

public static void yield()

通过Thread.yield()表示出让当前CPU的执行权,尽可能让线程执行均匀

插入线程/插队线程

public static void join()

t.join(); 把t线程插入到当前线程之前 会先执行t线程的代码

线程的生命周期

线程安全的问题

package com.lanqiao.study;/*** @author: lans* @date: 2025/4/1* @name: 刘宇*/
public class ThreadDemo3 {public static void main(String[] args) {MyThread t1 = new MyThread();MyThread t2 = new MyThread();MyThread t3 = new MyThread();t1.setName("窗口1");t2.setName("窗口2");t3.setName("窗口3");t1.start();t2.start();t3.start();}
}
package com.lanqiao.study;/*** @author: lans* @date: 2025/4/1* @name: 刘宇*/
public class MyThread extends Thread {int ticket = 0;@Overridepublic void run() {
//        for(int i=0;i<100;i++){
//            try{
//                Thread.sleep(1000);
//            }catch(Exception e){
//                e.printStackTrace();
//            }
//            System.out.println(getName()+"@"+i);
//        }while (true) {if(ticket<100){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}ticket++;System.out.println(getName()+"正在卖第"+ticket+"张票");}else{break;}}}public MyThread(String name) {super(name);}public MyThread() {}
}

如本题中会出现问题:

1.相同的票卖了多次

2.出现了超出范围的票

线程执行时,有随机性

同步代码块

把操作共享数据的代码锁起来

synchronized(锁){
操作共享数据的代码

}

特点1:锁默认打开,有一个线程进行去了,锁自动关上

特点2:里面的代码全部执行完毕,线程出来,锁自动打开

package com.lanqiao.study;/*** @author: lans* @date: 2025/4/1* @name: 刘宇*/
public class MyThread extends Thread {static int ticket = 0;//锁对象一定是唯一的static Object obj = new Object();@Overridepublic void run() { while (true) {synchronized(obj){if(ticket<100){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}ticket++;System.out.println(getName()+"正在卖第"+ticket+"张票");}else{break;}}}}public MyThread(String name) {super(name);}public MyThread() {}
}

注意锁放的位置

锁对象一定要是唯一的

synchronized(MyThread.class)这种写法保险

同步方法

StringBuffer是线程安全的 因为是同步方法

package com.lanqiao.study;/*** @author: lans* @date: 2025/4/2* @name: 刘宇*/
public class MyThread1 extends Thread {static int ticket=0;//同步代码块的方式
//    @Override
//    public void run() {
//        while(true){
//            synchronized(MyThread1.class){
//                if(ticket==100){
//                    break;
//                }else{
//                    try {
//                        Thread.sleep(100);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    ticket++;
//                    System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票!!!");
//                }
//            }
//        }
//    }//同步方法@Overridepublic void run() {while (true) {if(method())break;}}private synchronized boolean method(){if(ticket==100){return true;}else{try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}ticket++;System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票!!!");}return false;}
}
package com.lanqiao.study;/*** @author: lans* @date: 2025/4/2* @name: 刘宇*/
public class ThreadDemo4 {public static void main(String[] args) {MyThread t1 = new MyThread();MyThread t2 = new MyThread();MyThread t3 = new MyThread();t1.setName("t1");t2.setName("t2");t3.setName("t3");t1.start();t2.start();t3.start();}
}

lock锁

即可手动开关锁

public class MyThread1 extends Thread {static int ticket=0;//同步代码块的方式//加static使多个对象共享同一把锁static Lock lock = new ReentrantLock();@Overridepublic void run() {while(true){
//            synchronized(MyThread1.class){lock.lock();try {if (ticket == 100) {break;} else {Thread.sleep(100);ticket++;System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票!!!");}}catch (InterruptedException e) {e.printStackTrace();}finally {//保证释放锁lock.unlock();}}}}
}

死锁

避免锁嵌套

生产者和消费者(等待唤醒机制)

生产者消费者模式是一个十分经典的多线程协作的模式.notify wait

类似于ABABABABABABABABABABA...

void wait() 当前线程等待,直到被其他线程唤醒

void notify() 随机唤醒单个线程

void notifyAll()唤醒所有线程

public class ThreadDemo5 {public static void main(String[] args) {cook c = new cook();foodie f = new foodie();c.setName("厨师");f.setName("吃货");c.start();f.start();}
}
package com.lanqiao.study;/*** @author: lans* @date: 2025/4/2* @name: 刘宇*/
public class cook extends Thread{@Overridepublic void run() {while(true){synchronized(desk.lock){if(desk.count==0){break;}else{if(desk.foodFlag==1){//判断桌子上是否有食物try {//有就等待desk.lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}else{//没有面条就制作食物System.out.println("厨师做了一碗面条");//修改桌子上食物状态desk.foodFlag=1;//叫醒等待的消费者desk.lock.notifyAll();}}}}}
}
package com.lanqiao.study;/*** @author: lans* @date: 2025/4/2* @name: 刘宇*/
public class foodie extends Thread{/*1.循环2.同步代码块3.判断共享数据是否到了末尾 到了4.没到末尾*/@Overridepublic void run() {while(true){synchronized(desk.lock){if(desk.count==0){break;}else{//判断是否有面条if(desk.foodFlag==0){//没等待try {desk.lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}else{//把吃的总数-1desk.count--;//有开吃System.out.println("在吃面条,还能吃"+desk.count+"碗");//吃完后唤醒厨师继续做desk.lock.notifyAll();//修改桌子的状态desk.foodFlag=0;}}}}}
}
package com.lanqiao.study;/*** @author: lans* @date: 2025/4/2* @name: 刘宇*/
public class desk {//0是没有面条 1有public static int foodFlag=0;//总个数public static int count=10;//锁对象public static Object lock=new Object();
}

等待唤醒机制(阻塞队列方式实现)

public class ThredDemo {public static void main(String[] args) {//需要指定上限//1.创建阻塞队列对象 将对象传递给cook foodie实现共用同一个对象ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(1);//2.创建线程的对象,并把阻塞队列传递过去Cook c = new Cook(queue);Foodie f = new Foodie(queue);//3.开启线程c.start();f.start();}
}
public class Cook extends Thread {ArrayBlockingQueue<String> queue;public Cook(ArrayBlockingQueue<String> queue) {this.queue = queue;}@Overridepublic void run() {while(true){//不断的把面条放到阻塞队列中try {queue.put("面条");//锁在阻塞队列里面 打印语句在外导致输出结果看的不方便但执行是合理的System.out.println("厨师放了一碗面条");} catch (InterruptedException e) {e.printStackTrace();}}}
}public class Foodie extends Thread {ArrayBlockingQueue<String> queue;public Foodie(ArrayBlockingQueue<String> queue) {this.queue = queue;}@Overridepublic void run() {while (true) {String food = null;try {food = queue.take();System.out.println(food);} catch (InterruptedException e) {e.printStackTrace();}}}
}

多线程的6种状态

练习1.抢红包

100元三个包 五个人抢

package com.lanqiao.homework;/*** @author: lans* @date: 2025/4/3* @name: 刘宇* 抢红包 100块分成了3个包 现在有5个人去抢 红包是共享数据*/
public class thread1 {public static void main(String[] args) {//创建线程对象MyThread1 t1 = new MyThread1();MyThread1 t2 = new MyThread1();MyThread1 t3 = new MyThread1();MyThread1 t4 = new MyThread1();MyThread1 t5 = new MyThread1();t1.setName("ly");t2.setName("鸡哥");t3.setName("31");t4.setName("sm");t5.setName("jm");t1.start();t2.start();t3.start();t4.start();t5.start();}}

package com.lanqiao.homework;import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @author: lans* @date: 2025/4/3* @name: 刘宇*/
public class MyThread1 extends Thread {static BigDecimal money = BigDecimal.valueOf(100);//100块分3个包static int count = 3;//红包最小金额static final BigDecimal MIN = BigDecimal.valueOf(0.01);private static final Lock lock = new ReentrantLock(true); // 启用公平锁@Overridepublic void run() {//同步代码块lock.lock();try {if (count == 0) {System.out.println(getName() + "没有抢到红包");} else {//判断是否到末尾BigDecimal price;if (count == 1) {//此时是最后一个红包 无需随机 即剩下的所有金额price = money;} else {//表示是第一二次Random r = new Random();//第一个红包最大99.98double bounds = money.subtract(BigDecimal.valueOf(count - 1).multiply(MIN)).doubleValue();//范围0.01-boundsprice = BigDecimal.valueOf(r.nextDouble(bounds));}price = price.setScale(2, RoundingMode.HALF_UP);money = money.subtract(price);count--;System.out.println(getName() + "抢到了" + price + "元");}} finally {lock.unlock();}}
}

练习2.抽奖箱抽奖

package com.lanqiao.homework;import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;/*** @author: lans* @date: 2025/4/3* @name: 刘宇*/
public class thread2 {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<Integer>();Collections.addAll(list,10,5,20,50,100,200,500);MyThread2 t1 = new MyThread2(list);MyThread2 t2 = new MyThread2(list);t1.setName("抽奖箱1");t2.setName("抽奖箱2");t1.start();t2.start();}
}
package com.lanqiao.homework;import java.util.ArrayList;
import java.util.Collections;/*** @author: lans* @date: 2025/4/3* @name: 刘宇*/
public class MyThread2 extends Thread {//用集合来存放奖品,在构造方法中赋值集合ArrayList<Integer> list;public MyThread2(ArrayList<Integer> list) {this.list = list;}@Overridepublic void run() {//1.循环//2.同步代码块//3.判断while(true){synchronized (MyThread2.class){if(list.size()==0){break;}else{//shuffle方法打乱集合然后抽取Collections.shuffle(list);int price = list.remove(0);System.out.println(getName()+"又产生了一个"+price+"元大奖");}}//让线程休眠 结果尽可能随机try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}
}

线程池

以前写多线程的弊端 用到线程就创建 用完后消失 这样是浪费资源的

创建一个线程池可以解决这个问题.

通过Executors:线程池的工具类,调用方法返回不同类型的线程池对象

public static ExecutorService newCachedThreadPool(int nThreads);

线程池核心原理
  1. 创建一个池子,池子中是空的
  2. 提交任务时,池子会创建新的线程对象,任务执行完毕,线程归还给池子下回再次提交任务时,不需要创建新的线程,直接复用已有的线程即可
  3. 但是如果提交任务时,线程池中没有空闲线程,也无法创建新的线程,任务就会排队等待.
package com.lanqiao.homework;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** @author: lans* @date: 2025/4/3* @name: 刘宇*/
public class MyThreadPoolDemo {public static void main(String[] args) throws InterruptedException {
//        public static ExecutorService newCachedThreadPool(int nThreads);//1.获取线程池对象
//        ExecutorService pool1 = Executors.newCachedThreadPool();ExecutorService pool1 = Executors.newFixedThreadPool(3);//2.提交任务pool1.submit(new MyRunnable());pool1.submit(new MyRunnable());pool1.submit(new MyRunnable());pool1.submit(new MyRunnable());pool1.submit(new MyRunnable());pool1.submit(new MyRunnable());pool1.submit(new MyRunnable());pool1.submit(new MyRunnable());pool1.submit(new MyRunnable());//3.销毁线程池
//        pool1.shutdown();}
}
package com.lanqiao.homework;/*** @author: lans* @date: 2025/4/3* @name: 刘宇*/
public class MyRunnable implements Runnable{@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName()+"----"+i);}}
}
关键字:望野博物馆阎焰简历_重庆本地生活平台_seo实战优化_站长之家网站排行榜

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: