Java进阶之多线程

26、JAVA进阶——多线程 一、认识进程和线程 | 1. 进程 | 2. 线程 | 3. 多线程的优势 | 二、编写线程类 | 三、线程状态和线程调度 | 1.线程的状态 | 2.线程调度 阅读详情

1、程序、进程、线程

程序:是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。

进程(Process):是执行程序的一次执行过程,是一个动态的概念,是系统资源分配的单位。

线程(Thread):通常在一个进程中可以包含若干个线程,一个进程中至少有一个线程,不然没有存在的意义。线程是CPU调度和执行的单位。

很多多线程是模拟出来的,真正的多线程是指有多个cpu,即多核,如服务器。如果是模拟出来的多线程,即在一个cpu的情况下,在同一时间点,cpu只能执行一个代码,因为切换的很快,所以就有同时执行的错觉。

  • 线程就是独立的执行路径;
  • 在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程;
  • main()称之为主线程,为系统的入口,用于执行整个程序;
  • 在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为的干预的;
  • 对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制;
  • 线程会带来额外的开销,如cpu调度时间,并发控制开销;
  • 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致。

2、线程的创建

  • Thread class——->继承Thread类
  • Runnable接口——>实现Runnable接口
  • Callable接口——>实现Callable接口

方式一:(1)自定义线程类继承Thread类;(2)重写run()方法,编写线程执行体;(3)创建线程对象,调用start()方法启动线程

 1 public class StartThread extends Thread{ //1、自定义线程类继承Thread类
 2     @Override //2、重写run()方法,编写线程执行体
 3     public void run() {
 4         for (int i = 0; i < 100; i++) {
 5             System.out.println("run"+i);
 6         }
 7     }
 8 
 9     public static void main(String[] args) {
10         StartThread startThread = new StartThread();
11         startThread.start(); //3、创建线程对象,调用start()方法启动线程
12         for (int i = 0; i < 500; i++) {
13             System.out.println("main"+i);
14         }
15     }
16 }

线程不一定立即执行,由CPU安排调度

方式二:(1)自定义线程类实现Runnable接口;(2)实现run()方法,编写线程执行体;(3)创建线程对象,调用start()方法启动线程

 1 public class MyRunnable implements Runnable{  //1、自定义线程类实现Runnable接口
 2     @Override //2、重写run()方法,编写线程执行体
 3     public void run() {
 4         for (int i = 0; i < 100; i++) {
 5             System.out.println("run"+i);
 6         }
 7     }
 8 
 9     public static void main(String[] args) {
10         MyRunnable myRunnable = new MyRunnable();
11         //3、创建线程对象,调用start()方法启动线程,代理
12         new Thread(myRunnable).start();
13 
14         for (int i = 0; i < 500; i++) {
15             System.out.println("main"+i);
16         }
17     }
18 }

推荐使用实现Runnable接口,避免单继承局限性。

方式三:(1)实现Callable接口,需要返回值类型;(2)重写call方法,需要抛出异常;(3)创建目标对象;(4)创建执行服务:ExecutorService s = Executors.newFixedThreadPool(1);

(5)提交执行:Future result = s.submit(t);(6)获取结果:boolean r = result.get();(7)关闭服务:s.shutdownNow();

 1 public class MyCallable implements Callable<Boolean> { //1、实现Callable接口,需要返回值类型
 2     @Override //2、重写call方法,需要抛出异常;
 3     public Boolean call() throws Exception {
 4         for (int i = 0; i < 100; i++) {
 5             System.out.println(Thread.currentThread().getName()+":"+i); //获取当前线程名字
 6         }
 7         return true;
 8     }
 9 
10     public static void main(String[] args) {
11         //3、创建目标对象;
12         MyCallable m1 = new MyCallable();
13         MyCallable m2 = new MyCallable();
14         MyCallable m3 = new MyCallable();
15         //4、创建执行服务:
16         ExecutorService s = Executors.newFixedThreadPool(3);
17         //5、提交执行:
18         Future<Boolean> r1 = s.submit(m1);
19         Future<Boolean> r2 = s.submit(m2);
20         Future<Boolean> r3 = s.submit(m3);
21         //6、获取结果:
22         try {
23             boolean rs1 = r1.get();
24             boolean rs2 = r2.get();
25             boolean rs3 = r3.get();
26         } catch (InterruptedException | ExecutionException e) {
27             throw new RuntimeException(e);
28         }
29         //7关闭服务:
30         s.shutdownNow();
31     }
32 }

3、Lambda表达式 (JDK8)

  • 希腊字母表中排序第十一位的字母
  • 避免匿名内部类定义过多
  • 其实质属于函数式编程的概念

(params) -> expression[表达式]

(params) -> statement[语句]

(params) -> {statements}

函数式接口:任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口。对于函数式接口,我们可以通过lambda表达式来创建该接口的对象。

 1 public class TestLambda {
 2     //静态内部类
 3     static class Like2 implements ILike{
 4         @Override
 5         public void like() {
 6             System.out.println("I like lambda2");
 7         }
 8     }
 9     public static void main(String[] args) {
10         //局部内部类
11         class Like3 implements ILike{
12             @Override
13             public void like() {
14                 System.out.println("I like lambda3");
15             }
16         }
17 
18         ILike like = new Like1();
19         like.like();
20         like = new Like2();
21         like.like();
22         like = new Like3();
23         like.like();
24         //匿名内部类
25         like = new ILike() {
26             @Override
27             public void like() {
28                 System.out.println("I like lambda4");
29             }
30         };
31         like.like();
32         //lambda表达式
33         //(1)
34         like = () -> {
35             System.out.println("I like lambda5");
36         };
37         like.like();
38         //(2)花括号简化,只允许有一行代码,多行必须要用代码块
39         like = () -> System.out.println("I like lambda6");
40         like.like();
41         //(3)若带参数,可去掉小括号简化,可去掉返回类型简化
42         //like = (int a,int b) -> System.out.println("I like lambda6");
43         //like = a,b -> System.out.println("I like lambda6");
44     }
45 
46 }
47 interface ILike{  //函数式接口
48     void like();
49 }
50 //实现类
51 class Like1 implements ILike{
52     @Override
53     public void like() {
54         System.out.println("I like lambda1");
55     }
56 }

4、线程状态

5、停止线程

不推荐使用JDK提供的stop()、destroy()方法。

建议使用一个标志位进行终止变量,当flag=false,则终止线程运行。

 1 public class TestStop implements Runnable{
 2 
 3     //设置标志位
 4     private boolean flag = true;
 5 
 6     public static void main(String[] args) {
 7         TestStop testStop = new TestStop();
 8         new Thread(testStop).start(); //开启线程
 9         for (int i = 0; i < 500; i++) {
10             if(i == 200){ //当主线程跑到200时,停止run线程
11                 testStop.stop();
12                 System.out.println("stop run");
13             }
14             System.out.println("main"+i);
15         }
16     }
17     //提供停止线程的方法,转换标志位
18     public void stop(){
19         this.flag = false;
20     }
21 
22     @Override
23     public void run() {
24         int i = 0;
25         while (flag){
26             System.out.println("run"+ i++);
27         }
28     }
29 }

6、线程休眠 sleep()

  • sleep(时间)指定当前线程阻塞的毫秒数;
  • sleep存在异常InterruptedException;
  • sleep时间达到后线程进入就绪状态;
  • sleep可以模拟网络延时,倒计时等;
  • 每一个对象都有一个锁,sleep不会释放锁

7、线程礼让 yield()

  • 礼让线程,让当前正在执行的线程暂停,但不阻塞;
  • 将线程从运行状态转为就绪状态
  • 让cpu重新调度,礼让不一定成功,看cpu

8、线程强制执行 join()

  • join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞,就是插队

9、线程状态观测

Thread.State state = thread.getState();

  • NEW : 尚未启动的线程处于此状态;
  • RUNNABLE :在Java虚拟机中执行的线程处于此状态;
  • BLOCKED :被阻塞等待监视器锁定的线程处于此状态;
  • WAITING :正在等待另一个线程执行待定动作的线程处于此状态;
  • TIMED_WAITING :正在等待另一个线程执行动作达到指定等待时间的线程处于此状态;
  • TERMINATED :已退出的线程处于此状态

10、线程的优先级

  • Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。
  • 线程的优先级用数字表示,范围从1-10。优先级高的不一定会先执行。优先级的设定建议在start()调度前。
  1. Thread.MIN_PRIORITY = 1;
  2. Thread.MAX_PRIORITY = 10;
  3. Thread.NORM_PRIORITY = 5;
  • 使用以下方式来改变或获取优先级
  1. getPriority().setPriority(int p);

  2. getPriority().getPriority();

    1 public class TestPriority implements Runnable{
    2 @Override
    3 public void run() {
    4 System.out.println(Thread.currentThread().getName()+“–>”+Thread.currentThread().getPriority());
    5 }
    6
    7 public static void main(String[] args) {
    8 //主线程
    9 System.out.println(Thread.currentThread().getName()+“–>”+Thread.currentThread().getPriority());
    10 TestPriority testPriority = new TestPriority();
    11 Thread t1 = new Thread(testPriority);
    12 Thread t2 = new Thread(testPriority);
    13 Thread t3 = new Thread(testPriority);
    14 Thread t4 = new Thread(testPriority);
    15
    16 t1.setPriority(Thread.MAX_PRIORITY);
    17 t1.start();
    18 t2.setPriority(Thread.MIN_PRIORITY);
    19 t2.start();
    20 t3.setPriority(8);
    21 t3.start();
    22 t4.setPriority(4);
    23 t4.start();
    24 }
    25 }

优先级低只是意味着获得调度的概率低,并不是优先级低就不会被调用了,要看cpu的调度。

11、守护线程 setDaemon()

  • 线程分为用户线程和守护线程
  • 虚拟机必须确保用户线程执行完毕
  • 虚拟机不用等待守护线程执行完毕
  • 如后台记录操作日志,内存监控,垃圾回收等…

12、线程同步

并发:同一个对象被多个线程同时操作。

线程同步:就是一种等待机制,多个需要同时访问此对象是线程进入这个对象的等待池形成队列,等待前面线程使用完毕,下一个线程在使用。

形成条件:队列 + 锁

在访问时加入锁机制synchronized,当一个线程获得对象的排它锁,独占资源,其他线程必须等待,使用后释放锁即可。但也存在一些问题:

  • 一个线程持有锁会导致其他所有需要此锁的线程挂起;
  • 在多线程竞争下,加锁,释放锁会导致比较多的上下文切换和调度延时,引起性能问题;
  • 如果一个优先级高的线程等待一个优先级低的线程释放锁,会导致优先级倒置,引起性能问题。

13、同步方法

(1)synchronized关键字包括两种用法:synchronized方法和synchronized块。

(2)synchronized方法控制对“对象”的访问,每个对象对应一把锁,每个synchronized方法都必须获得调用该方法的对象的锁才能执行,否则线程会阻塞,方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行。

缺陷:若将一个大的方法申明为synchronized,将会影响效率。

 1 public class SafeBuyTicket{
 2     public static void main(String[] args) {
 3         BuyTicket station = new BuyTicket();
 4         new Thread(station ,"lily").start();
 5         new Thread(station ,"Ming").start();
 6         new Thread(station ,"Jenny").start();
 7 
 8     }
 9 }
10 class BuyTicket implements Runnable{
11     private int ticketNum = 10;
12     boolean flag = true;
13     @Override
14     public void run() {
15         while(flag){
16             try {
17                 buy();
18             } catch (InterruptedException e) {
19                 throw new RuntimeException(e);
20             }
21         }
22     }
23     //同步方法
24     private synchronized void buy() throws InterruptedException {
25         if(ticketNum <= 0){
26             flag = false;
27             return;
28         }
29         Thread.sleep(100);
30         System.out.println(Thread.currentThread().getName() + " get " + ticketNum--);
31     }
32 }

14、同步块

synchronized(obj){}

obj称之为同步监听器:

(1)obj可以是任何对象,但是推荐使用共享资源作为同步监视器

(2)同步方法中无需指定同步监视器,因为同步方法的同步监视器就是this,就是这个对象本身,或者是class。

同步监视器的执行过程:

(1)第一个线程访问,锁定同步监视器,执行其中代码;

(2)第二个线程访问,发现同步监视器被锁定,无法访问;

(3)第一个线程访问完毕,解锁同步监视器;

(4)第二个线程访问,发现同步监视器没有锁,然后锁定并访问;

 1 public class SafeList {
 2     public static void main(String[] args) {
 3         List<String> list = new ArrayList<String>();
 4         for (int i = 0; i < 1000; i++) {
 5             new Thread(()->{
 6                 //代码块
 7                 synchronized (list){
 8                     list.add(Thread.currentThread().getName());
 9                 }
10             }).start();
11         }
12         try {
13             Thread.sleep(300);
14         } catch (InterruptedException e) {
15             throw new RuntimeException(e);
16         }
17         System.out.println(list.size());
18     }
19 }

CopyOnWriteArrayList是JUC包下的一个线程安全集合。

15、死锁

多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能运行,而导致两个或者多个线程都在等待对方释放的资源,都停止执行的情形。某一个同步块同时拥有“两个以上对象的锁”时,就可能会发生“死锁”的问题。

死锁避免方法:

  • 产生死锁的四个必要条件:(破其一可避免死锁)

(1)互斥条件:一个资源每次只能被一个进程使用;

(2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放;

(3)不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺;

(4)循环等条件:若干进程之前形成一种头尾相接的循环等待资源关系。

16、Lock

  • JDK5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步。同步锁使用Lock对象充当;

  • java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象;

  • ReentrantLock类实现Lock,它拥有与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁。

    1 class A {
    2 private final ReentrantLock lock = new ReentrantLock();
    3 public void m(){
    4 lock.lock();
    5 try {
    6 //保证线程安全的代码
    7 }catch (Exception e){
    8
    9 }finally {
    10 lock.unlock();
    11 }
    12 }
    13 }

17、Lock与synchronized的对比

  • Lock是显式锁(手动开启和关闭锁),synchronized是隐式锁,出了作用域自动释放;
  • Lock只有代码块锁,synchronized有代码块锁和方法锁;
  • 使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性;
  • 优先使用顺序:Lock > 同步代码块 > 同步方法

18、线程协作

生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件。

  • 对于生产者,没有生产产品之前,要通知消费者等待,而生产了产品之后,又需要马上通知消费者消费;
  • 对于消费者,在消费之后,要通知生产者已经结束消费,需要生产新的产品以供消费;
  • 在生产者消费问题中,仅有synchronized是不够的:synchronized可阻止并发更新同一个共享资源,实现了同步;synchronized不能用来实现不同线程之间的消息传递(通信)。

Java提供了几个方法解决线程之间的通信问题:

  • wait():表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁
  • wait(long timeout):指定等待的毫秒数
  • notify():唤醒一个处于等待状态的线程
  • notifyAll():唤醒同一个对象上所有调用wait()方法的线程,优先级别高的线程优先调度

注意:均是Object类的方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常IllegalMonitorStateException.

解决方式1:

并发协作模型“生产者/消费者模式”—>管程法

(1)生产者:负责生产数据的模块(可能是方法,对象,线程,进程);

(2)消费者:负责处理数据的模块(可能是方法,对象,线程,进程);

(3)缓冲区:消费者不能直接使用生产者的数据,他们之间有个“缓冲区”。

解决方式2:

并发协作模型“生产者/消费者模式”—>信号灯法(通过标志位来实现)

19、线程池

经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大。解决思路,可以提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池子中,避免频繁创建销毁,实现重复利用。这样能减少创建新线程的时间,提高响应速度;重复利用线程池中线程,降低资源消耗;便于线程管理等。

  • corePoolSize:核心池的大小
  • maxnumPoolSize:最大线程数
  • keepAliveTime:线程没有任务时最多保持多长时间后会终止

JDK5.0起提供了线程池相关的API:ExecutorService和Executors

ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor

  • void execute(Runnable command):执行任务/命令,没有返回值,一般用来执行Runnable
  • Future submit(Callable task):执行任务,有返回值,一般又来执行Callable
  • void shutdown():关闭连接池

Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池。

 1 public class TestPool {
 2     public static void main(String[] args) {
 3         //创建服务,创建线程池
 4         ExecutorService service = Executors.newFixedThreadPool(10);
 5         //执行
 6         service.execute(new MyThread());
 7         service.execute(new MyThread());
 8         service.execute(new MyThread());
 9         service.execute(new MyThread());
10         //关闭连接
11         service.shutdown();
12     }
13 
14 }
15 
16 class MyThread implements Runnable{
17 
18     @Override
19     public void run() {
20         System.out.println(Thread.currentThread().getName());
21     }
22 }
java多线程进阶 这本书对JAVA多线程进阶帮助非常之大而且详细、融会贯通、看了必定打通多线程任督二脉 立即下载

相关推荐

ThinkPad X230魔改指南:从博通网卡驱动到1080P屏显全攻略(附Sonoma避坑清单)

本文详细介绍了ThinkPad X230的全面改造方案,包括博通网卡驱动(BCM94352HMB)的安装与调试、1080P屏幕改装技术以及macOS Sonoma系统的适配优化。通过硬件升级和软件调优,使这台经典商务本焕发新生,适合DIY爱好者和技术极客参考实践。

weixin_30379531的博客 586

Java多线程进阶

文章包含常见的锁策略,CAS,JUC以及多线程执行过程,线程状态,线程池等的介绍,以及多线程中可能出现问题的总结

小S的博客 1206

西门子S7-1200/1500 PLC编程与应用技巧

西门子S7-1200 PLC是一款紧凑型的控制器,适用于小型到中型的自动化控制任务。紧凑设计:集成了I/O模块,减少了控制柜的空间需求。高性能:高达25µs的扫描时间,能够快速响应。模块化扩展:支持扩展输入输出模块、通信模块和智能模块,满足不同的应用需求。多种编程语言:支持Ladder图(梯形图)、功能块图(FBD)、结构化文本(ST)等多种编程语言。西门子S7-1200与S7-1500 PLC是强大且灵活的工业控制系统,适用于各种自动化应用。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 2673

【浅学Java】多线程进阶

CAS全称为compareandswap,即“比较并交换”的意思,它通过一次CPU的占用就可以同时完成“读取内存,比较是否相等,修改内存”这三个步骤,达到“比较并交换”效果。它的底层是一个原子的硬件指令。...

qq_52276036的博客 1332

Sparse4Dv3

instance_feature也设置为nn.Parameter。修正分支2*(linear->relu->linear->relu->layernorm)->linear->scale,分类分枝2*(linear->relu->layernorm)->linear(256,9),质量评估分枝2*(linear->relu->layernorm)->linear(256,2)。每组两类instance,1是加上范围(-x,x)内均匀分布噪声,2是加上(-2x,-x)U(x,2x)范围内均匀分布噪声。

yuanl15的博客 1351

ICESat-2数据下载及处理分析随笔

ICESat-2全称是Ice,Cloud and land Elevation Satellite -2。看名字我们能知道它的任务是测ice,cloud和land elevation,而且这是一个Satellite,是一颗卫星。那么这里我们就要分清ICESat-2和ATLAS的关系,ICESat-2是星载平台,是一个space observatory,ATLAS是这个星载平台上搭载的单光子激光雷达系统。

u011322358的博客 1万+

【Java】多线程(进阶)

CAS 操作的 ABA 问题指的是,在某个线程执行 CAS 操作之前,共享变量的值被改变多次,并最终返回到了原始值,因此在执行 CAS 操作时,虽然当前变量的值与期望值相等,但实际上它已经被其他线程修改过了。它们的获取顺序是相反的,即 thread1 先获取 lock1,再获取 lock2,而 thread2 先获取 lock2,再获取 lock1。公平锁是一种按照线程请求的顺序来分配锁的锁机制。**当多个线程竞争一个公平锁时,锁会按照先来后到的顺序将锁分配给等待时间最长的线程,保证了线程获取锁的公平性。

m0_72670269的博客 693

Deepseek+Word插件:一键搞定论文翻译与润色的学术写作新革命

本文介绍了Deepseek Word插件如何革新学术写作流程,实现论文翻译与润色的一键操作。该插件深度集成于Word环境,能智能完成中英互译、语法修正、术语统一及逻辑优化,显著提升写作效率与文本质量,是研究者的高效AI助手。

weixin_29252171的博客 512

进阶Java学习——多线程

学习多线程

qq_45102119的博客 467

嵌入式开发必备:aarch64-linux-gnu-gcc交叉编译工具链保姆级安装指南(含常见错误解决)

本文详细介绍了aarch64-linux-gnu-gcc交叉编译工具链的安装与配置方法,涵盖从系统软件源安装到Linaro二进制包部署的全流程。针对嵌入式开发中常见的依赖错误、版本冲突等问题提供实用解决方案,并分享性能优化技巧与项目集成经验,帮助开发者高效完成ARM64设备的跨平台开发。

yoga7的博客 1030

FPGA时钟设计陷阱:为什么你的MRCC引脚总触发Place 30-675错误?

本文深入解析FPGA开发中常见的Place 30-675错误,揭示MRCC引脚与时钟资源分配的关键问题。通过对比MRCC与普通IO引脚特性,分析错误根源,并提供时钟约束优化、IP核重配置和手动布局三套解决方案,帮助工程师规避时钟设计陷阱,提升FPGA系统稳定性。

potato的博客 693

Java多线程进阶详解

使用CAS编写代码,比较然后交换。大部分没问题,但在极端情况下有问题。比如银行取钱一个人账户是1000,取款500,假设是按照CAS的方式来执行的。按取款卡了一下,又按了一下。就有两个线程来进行操作,如果恰好有人转账500,则会出现bug。如何处理ABA问题呢?使用账户余额判定,本身就不科学。属于能加也能减。引入一个只能加的版本号,每次取钱或者存钱,版本号就+1,就可以进一步解决ABA问题。CAS的核心就在于说,通过数值没变=》中间没有别的线程覆盖。

2302_80113478的博客 1148

RTC 实时时钟实验

如果在 RTC_CR 寄存器中设置了相应的允许位,则在每个TR_CLK 周期中 RTC 产生一个中断(秒中断)。void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data) // 往备份区域写用户数据的函数 (这个函数的第一个参数就是寄存器的标号了,这个是通过宏定义定义的)存储在 RTC_ALR 寄存器中的可编程时间相比较,如果 RTC_CR 控制寄存器中设置了相应允许位,比较匹配时将产生一个闹钟中断。寄存器操作完成,并同步之后,设置秒钟中断。

m0_55996456的博客 1205

JAVA多线程进阶

下面是实现原子类的伪代码,此处的 oldValue 在实际实现中是直接用寄存器存储的内容 ,value 是内存中的原始数据,CAS(value,oldValue,oldValue+1) 操作理解为,判定内存中的值和寄存器中的值是否一致,如果一致,就把内存中的value值设置为 oldValue+1,返回 true,循环结束;CAS的关键是先比较,再交换,在比较的过程中,当前值和旧值是相同时,就认为中间没有发生过改变,但是可能存在中间发生了改变,但多次改变后值不变的情况。读锁和读锁之间不存在互斥关系;

2301_81831660的博客 1071

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Java 多线程进阶

下断点调试信息,可以看到run()方法当前线程是“main@1”继续运行到run里面,当前线程仍然是“main@1”接下来看一下start()方法运行的线程结果,可以看到是两个线程。

xlsj雪松的博客 415

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Java多线程之进阶篇

ThreadPoolExecutor是线程池类。对于线程池,可以通俗的将它理解为“存放一定数量的一个线程集合。线程池允许若个线程同时运行,运行同时运行的线程数量就是线程池的容量。当添加到线程池中的线程超过它的容量时,会有一部分线程阻塞等待,线程池会通过相应的调度策略和拒绝策略,对添加到线程池中的线程进行管理。(2)

weixin_48374562的博客 969

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Java进阶12 多线程

线程、进程、开启线程的三种方式、线程安全和同步、线程通信、生产者消费者模式

summer_9823的博客 1236

【Java难点】多线程-进阶

在Java8中,CompletableFuture提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通过回调的方式处理计算结果,也提供了转换和组合 CompletableFuture的方法。**注意:**get/join方法放在complete之后,get/join方法永远不会阻塞,因为异步任务如果没计算完,complete方法会将value给get/join方法,get/join方法获取的是value,不会发生阻塞;

我爱写代码 我爱写代码 我爱写代码 957

java进阶--多线程学习

并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行。就好像两个人各拿一把铁锨在挖坑,一小时后,每人一个大坑。所以无论从微观还是从宏观来看,二者都是一起执行的。来个比喻:并发是一个人同时吃三个馒头,而并行是三个人同时吃三个馒头。并行是指多个处理器或者是多核的处理器同时处理多个不同的任务。并发是逻辑上的同时发生,而并行是物理上的同时发生。并发是指一个处理器同时处理多个任务。

m0_74825409的博客 385

Java进阶学习——Java多线程知识的理解

1)自定义多线程类PrimThread求解整数begin到end之间的素数; (2)定义主类ForkAndJoin,利用PrimThread创建多个线程求解1到10000000之间的素数和,要求输出计算时间。 Java多线程理解 synchronized(this)和synchronized(object) scheduleWithFixedDelay()和scheduleWithFixedRate()区别 invokeall()和fork()以及invoke()方法对比 join()方法

许帅的博客 835

Java EE初阶——多线程进阶

CAS(Compare-And-Swap,比较并交换)是一种无锁(Lock-Free)的原子操作机制,用于在多线程环境下实现变量的同步。它通过硬件支持(如 CPU 指令)保证操作的原子性,避免了传统锁机制的线程阻塞和上下文切换开销,适用于高并发场景下的轻量级同步。内存地址(V):要更新的变量所在的内存位置。旧值预期(A):操作前假设的变量当前值。新值(B):准备更新的新值。从内存地址 V 中读取当前值V_cur。比较V_cur是否等于预期值 A:如果相等。

2302_80250536的博客 774

Java进阶篇之多线程

多线程是提升应用性能、提高并发能力的强大工具,但同时它也带来了复杂的同步与调度问题。理解和掌握线程的生命周期、同步机制、线程池等概念,将有助于你写出高效、稳定的并发程序。👨‍💻👩‍💻今天我们通过示例代码和对比分析,深入了解了 Java 多线程的基本概念和常见技巧,掌握了如何通过线程池、高效的同步机制以及合理的设计来提升程序性能。🚀在接下来的文章中,我们将继续探讨Java中线程的创建和运行以及其他重要特性,敬请期待!👉😊。

code2cat的博客 917
上一篇: idea新建一个springboot项目
下一篇: Linux(CentOS)安装 Nginx
普通网友
博客等级 码龄4年 3126粉丝 192原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值