iis服务器助手广告
返回顶部
首页 > 资讯 > 精选 >怎么快速了解Java多线程
  • 888
分享到

怎么快速了解Java多线程

2023-06-16 14:06:10 888人浏览 泡泡鱼
摘要

这篇文章主要讲解了“怎么快速了解Java多线程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么快速了解Java多线程”吧!线程线程的概念:线程(英语:Thread)是操作系统能够进行运算调

这篇文章主要讲解了“怎么快速了解Java多线程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么快速了解Java多线程”吧!

线程

线程的概念:

线程(英语:Thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(Lightweight Processes),但轻量进程更多指内核线程(Kernel Thread),而把用户线程(User Thread)称为线程。

1.1 线程与进程的区别

怎么快速了解Java多线程

进程:指在系统中正在运行的一个应用程序;程序一旦运行就是进程;进程——资源分配的最小单位。

线程:系统分配处理器时间资源的基本单元,或者说进程之内独立执行的一个单元执行流。线程——程序执行的最小单位。

也就是,进程可以包含多个线程,而线程是程序执行的最小单位。

1.2 线程的状态

怎么快速了解Java多线程

  •  NEW:线程刚创建

  •  RUNNABLE: 在JVM中正在运行的线程,其中运行状态可以有运行中RUNNING和READY两种状态,由系统调度进行状态改变。

  •  BLOCKED:线程处于阻塞状态,等待监视,可以重新进行同步代码块中执行

  •  WaiTING : 等待状态

  •  TIMED_WAITING: 调用sleep() join() wait()方法可能导致线程处于等待状态

  •  TERMINATED: 线程执行完毕,已经退出

1.3 Notify和Wait :

Notify和Wait 的作用

首先看源码给出的解释,这里翻译了一下:

Notify:唤醒一个正在等待这个对象的线程监控。如果有任何线程正在等待这个对象,那么它们中的一个被选择被唤醒。选择是任意的,发生在执行的酌情权。一个线程等待一个对象通过调用一个{@code wait}方法进行监视。

Notify()需要在同步方法或同步块中调用,即在调用前,线程也必须获得该对象的对象级别锁

Wait:导致当前线程等待,直到另一个线程调用{@link java.lang.Object#notify()}方法或{@link java.lang.Object#notifyAll()}方法。

换句话说,这个方法的行为就像它简单一样执行调用{@code wait(0)}。当前线程必须拥有该对象的监视器。

线程释放此监视器的所有权,并等待另一个线程通知等待该对象的监视器的线程,唤醒通过调用{@code notify}方法或{@code notifyAll}方法。然后线程等待,直到它可以重新取得监视器的所有权,然后继续执行。

Wait()的作用是使当前执行代码的线程进行等待,它是Object类的方法,该方法用来将当前线程置入预执行队列中,并且在Wait所在的代码行处停止执行,直到接到通知或被中断为止。

在调用Wait方法之前,线程必须获得该对象的对象级别锁,即只能在同步方法或同步块中调用Wait方法。

Wait和Sleep的区别:

  •  它们最大本质的区别是,Sleep()不释放同步锁,Wait()释放同步锁。

  •  还有用法的上的不同是:Sleep(milliseconds)可以用时间指定来使他自动醒过来,如果时间不到你只能调用Interreput()来强行打断;Wait()可以用Notify()直接唤起。

  •  这两个方法来自不同的类分别是Thread和Object

  •  最主要是Sleep方法没有释放锁,而Wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

1.4 Thread.sleep() 和Thread.yield()的异同

  •  相同 :Sleep()和yield()都会释放CPU。

  •  不同:Sleep()使当前线程进入停滞状态,所以执行Sleep()的线程在指定的时间内肯定不会执行;yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。Sleep()可使优先级低的线程得到执行的机会,当然也可以让同优先级和高优先级的线程有执行的机会;yield()只能使同优先级的线程有执行的机会。

1.5 补充:死锁的概念

死锁:指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

死锁产生的四个必要条件(缺一不可):

  •  互斥条件:顾名思义,线程对资源的访问是排他性,当该线程释放资源后下一线程才可进行占用。

  •  请求和保持:简单来说就是自己拿的不放手又等待新的资源到手。线程T1至少已经保持了一个资源R1占用,但又提出对另一个资源R2请求,而此时,资源R2被其他线程T2占用,于是该线程T1也必须等待,但又对自己保持的资源R1不释放。

  •  不可剥夺:在没有使用完资源时,其他线性不能进行剥夺。

  •  循环等待:一直等待对方线程释放资源。

我们可以根据死锁的四个必要条件破坏死锁的形成。

1.6 补充:并发和并行的区别

并发:是指在某个时间段内,多任务交替的执行任务。当有多个线程在操作时,把CPU运行时间划分成若干个时间段,再将时间段分配给各个线程执行。在一个时间段的线程代码运行时,其它线程处于挂起状。

并行:是指同一时刻同时处理多任务的能力。当有多个线程在操作时,CPU同时处理这些线程请求的能力。

区别就在于CPU是否能同时处理所有任务,并发不能,并行能。

1.7 补充:线程安全三要素

  •  原子性:Atomic包、CAS算法、Synchronized、Lock。

  •  可见性:Synchronized、Volatile(不能保证原子性)。

  •  有序性:Happens-before规则。

1.8 补充:如何实现线程安全

  •  互斥同步:Synchronized、Lock。

  •  非阻塞同步:CAS。

  •  无需同步的方案:如果一个方法本来就不涉及共享数据,那它自然就无需任何同步操作去保证正确性。

1.9 补充:保证线程安全的机制:

  •  Synchronized关键字

  •  Lock

  •  CAS、原子变量

  •  ThreadLocl:简单来说就是让每个线程,对同一个变量,都有自己的独有副本,每个线程实际访问的对象都是自己的,自然也就不存在线程安全问题了。

  •  Volatile

  •  CopyOnWrite写时复制

随着CPU核心的增多以及互联网迅速发展,单线程的程序处理速度越来越跟不上发展速度和大数据量的增长速度,多线程应运而生,充分利用CPU资源的同时,极大提高了程序处理速度。

创建线程的方法

继承Thread类:

public class ThreadCreateTest {      public static void main(String[] args) {          new MyThread().start();      }  }  class MyThread extends Thread {      @Override      public void run() {          System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());      }  }

实现Runable接口:

public class RunableCreateTest {      public static void main(String[] args) {          MyRunnable runnable = new MyRunnable();          new Thread(runnable).start();      }  }  class MyRunnable implements Runnable {      @Override      public void run() {          System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());      }  }

通过Callable和Future创建线程:

public class CallableCreateTest {      public static void main(String[] args) throws Exception {           // 将Callable包装成FutureTask,FutureTask也是一种Runnable          MyCallable callable = new MyCallable();          FutureTask<Integer> futureTask = new FutureTask<>(callable);          new Thread(futureTask).start();          // get方法会阻塞调用的线程          Integer sum = futureTask.get();          System.out.println(Thread.currentThread().getName() + Thread.currentThread().getId() + "=" + sum);      }  }  class MyCallable implements Callable<Integer> {      @Override      public Integer call() throws Exception {          System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId() + "\t" + new Date() + " \tstarting...");          int sum = 0;          for (int i = 0; i <= 100000; i++) {              sum += i;          }          Thread.sleep(5000);          System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId() + "\t" + new Date() + " \tover...");          return sum;      }  }

线程池方式创建:

实现Runnable接口这种方式更受欢迎,因为这不需要继承Thread类。在应用设计中已经继承了别的对象的情况下,这需要多继承(而Java不支持多继承,但可以多实现啊),只能实现接口。同时,线程池也是非常高效的,很容易实现和使用。

实际开发中,阿里巴巴开发插件一直提倡使用线程池创建线程,原因在下方会解释,所以上面的代码我就只简写了一些Demo。

2.1 线程池创建线程

线程池,顾名思义,线程存放的地方。和数据库连接池一样,存在的目的就是为了较少系统开销,主要由以下几个特点:

降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗(主要)。

提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。

提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性。

Java提供四种线程池创建方式:

  •  newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

  •  newFixedThreadPool创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

  •  newScheduledThreadPool创建一个定长线程池,支持定时及周期性任务执行。

  •  newSingleThreadExecutor创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

通过源码我们得知ThreadPoolExecutor继承自AbstractExecutorService,而AbstractExecutorService实现了ExecutorService。

public class ThreadPoolExecutor extends AbstractExecutorService  public abstract class AbstractExecutorService implements ExecutorService

怎么快速了解Java多线程

2.2 ThreadPoolExecutor介绍

实际项目中,用的最多的就是ThreadPoolExecutor这个类,而《阿里巴巴Java开发手册》中强制线程池不允许使用Executors去创建,而是通过New ThreadPoolExecutor实例的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

怎么快速了解Java多线程

我们从ThreadPoolExecutor入手多线程创建方式,先看一下线程池创建的最全参数。 

public ThreadPoolExecutor(int corePoolSize,                               int maximumPoolSize,                               long keepAliveTime,                               TimeUnit unit,                               BlockingQueue<Runnable> workQueue,                               ThreadFactory threadFactory,                               RejectedExecutionHandler handler) {         if (corePoolSize < 0 ||             maximumPoolSize <= 0 ||             maximumPoolSize < corePoolSize ||             keepAliveTime < 0)             throw new IllegalArgumentException();         if (workQueue == null || threadFactory == null || handler == null)             throw new NullPointerException();         this.corePoolSize = corePoolSize;         this.maximumPoolSize = maximumPoolSize;         this.workQueue = workQueue;         this.keepAliveTime = unit.toNanos(keepAliveTime);         this.threadFactory = threadFactory;         this.handler = handler;     }

参数说明如下:

  •  corePoolSize:线程池的核心线程数,即便线程池里没有任何任务,也会有corePoolSize个线程在候着等任务。

  •  maximumPoolSize:最大线程数,不管提交多少任务,线程池里最多工作线程数就是maximumPoolSize。

  •  keepAliveTime:线程的存活时间。当线程池里的线程数大于corePoolSize时,如果等了keepAliveTime时长还没有任务可执行,则线程退出。

  •  Unit:这个用来指定keepAliveTime的单位,比如秒:TimeUnit.SECONDS。

  •  BlockingQueue:一个阻塞队列,提交的任务将会被放到这个队列里。

  •  threadFactory:线程工厂,用来创建线程,主要是为了给线程起名字,默认工厂的线程名字:pool-1-thread-3。

  •  handler:拒绝策略,当线程池里线程被耗尽,且队列也满了的时候会调用。

2.2.1BlockingQueue

对于BlockingQueue个人感觉还需要单独拿出来说一下。

BlockingQueue:阻塞队列,有先进先出(注重公平性)和先进后出(注重时效性)两种,常见的有两种阻塞队列:ArrayBlockingQueue和LinkedBlockingQueue

队列的数据结构大致如图:

怎么快速了解Java多线程

队列一端进入,一端输出。而当队列满时,阻塞。BlockingQueue核心方法:1. 放入数据put2. 获取数据take。常见的两种Queue:

2.2.2 ArrayBlockingQueue

基于数组实现,在ArrayBlockingQueue内部,维护了一个定长数组,以便缓存队列中的数据对象,这是一个常用的阻塞队列,除了一个定长数组外,ArrayBlockingQueue内部还保存着两个整形变量,分别标识着队列的头部和尾部在数组中的位置。

一段代码来验证一下: 

 package map;      import java.util.concurrent.*;      public class MyTestMap {          // 定义阻塞队列大小          private static final int maxSize = 5;          public static void main(String[] args){              ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(maxSize);              new Thread(new Productor(queue)).start();              new Thread(new Customer(queue)).start();          }     }      class Customer implements Runnable {          private BlockingQueue<Integer> queue;          Customer(BlockingQueue<Integer> queue) {              this.queue = queue;          }          @Override          public void run() {              this.cusume();          }          private void cusume() {              while (true) {                  try {                      int count = (int) queue.take();                      System.out.println("customer正在消费第" + count + "个商品===");                      // 只是为了方便观察输出结果                      Thread.sleep(10);                  } catch (InterruptedException e) {                      e.printStackTrace();                  }              }          }      }      class Productor implements Runnable {          private BlockingQueue<Integer> queue;          private int count = 1;          Productor(BlockingQueue<Integer> queue) {              this.queue = queue;          }          @Override          public void run() {              this.product();          }          private void product() {              while (true) {                  try {                      queue.put(count);                      System.out.println("生产者正在生产第" + count + "个商品");                      count++;                  } catch (InterruptedException e) {                      e.printStackTrace();                  }              }          }      }    //输出如下  

2.2.3 LinkedBlockingQueue

基于链表的阻塞队列,内部也维护了一个数据缓冲队列。需要我们注意的是如果构造一个LinkedBlockingQueue对象,而没有指定其容量大小。

LinkedBlockingQueue会默认一个类似无限大小的容量(Integer.MAX_VALUE),这样的话,如果生产者的速度一旦大于消费者的速度,也许还没有等到队列满阻塞产生,系统内存就有可能已被消耗殆尽了。

2.2.4 LinkedBlockingQueue和ArrayBlockingQueue的主要区别

  •  ArrayBlockingQueue的初始化必须传入队列大小,LinkedBlockingQueue则可以不传入。

  •  ArrayBlockingQueue用一把锁控制并发,LinkedBlockingQueue俩把锁控制并发,锁的细粒度更细。即前者生产者消费者进出都是一把锁,后者生产者生产进入是一把锁,消费者消费是另一把锁。

  •  ArrayBlockingQueue采用数组的方式存取,LinkedBlockingQueue用node链表方式存取。

2.2.5handler拒绝策略

Java提供了4种丢弃处理的方法,当然你也可以自己实现,主要是要实现接口:RejectedExecutionHandler中的方法。

  •  AbortPolicy:不处理,直接抛出异常。

  •  CallerRunsPolicy:只用调用者所在线程来运行任务,即提交任务的线程。

  •  DiscardOldestPolicy:LRU策略,丢弃队列里最近最久不使用的一个任务,并执行当前任务。

  •  DiscardPolicy:不处理,丢弃掉,不抛出异常。

2.2.6线程池五种状态 

private static final int RUNNING    = -1 << COUNT_BITS;     private static final int SHUTDOWN   =  0 << COUNT_BITS;     private static final int STOP       =  1 << COUNT_BITS;     private static final int TIDYING    =  2 << COUNT_BITS;     private static final int TERMINATED =  3 << COUNT_BITS;

RUNNING:在这个状态的线程池能判断接受新提交的任务,并且也能处理阻塞队列中的任务。

SHUTDOWN:处于关闭的状态,该线程池不能接受新提交的任务,但是可以处理阻塞队列中已经保存的任务,在线程处于RUNNING状态,调用shutdown()方法能切换为该状态。

STOP:线程池处于该状态时既不能接受新的任务也不能处理阻塞队列中的任务,并且能中断现在线程中的任务。当线程处于RUNNING和SHUTDOWN状态,调用shutdownNow()方法就可以使线程变为该状态。

TIDYING:在SHUTDOWN状态下阻塞队列为空,且线程中的工作线程数量为0就会进入该状态,当在STOP状态下时,只要线程中的工作线程数量为0就会进入该状态。

TERMINATED:在TIDYING状态下调用terminated()方法就会进入该状态。可以认为该状态是最终的终止状态。

回到线程池创建ThreadPoolExecutor,我们了解了这些参数,再来看看ThreadPoolExecutor的内部工作原理:

怎么快速了解Java多线程

  •  判断核心线程是否已满,是进入队列,否:创建线程

  •  判断等待队列是否已满,是:查看线程池是否已满,否:进入等待队列

  •  查看线程池是否已满,是:拒绝,否创建线程

2.3深入理解ThreadPoolExecutor

进入Execute方法可以看到:

public void execute(Runnable command) {         if (command == null)             throw new NullPointerException();         int c = ctl.get();       //判断当前活跃线程数是否小于corePoolSize,如果小于,则调用addWorker创建线程执行任务         if (workerCountOf(c) < corePoolSize) {             if (addWorker(command, true))                 return;             c = ctl.get();         }       //如果不小于corePoolSize,则将任务添加到workQueue队列。         if (isRunning(c) && workQueue.offer(command)) {             int recheck = ctl.get();             if (! isRunning(recheck) && remove(command))                 reject(command);             else if (workerCountOf(recheck) == 0)                 addWorker(null, false);         }       //如果放入workQueue失败,则创建线程执行任务,如果这时创建线程失败(当前线程数不小于maximumPoolSize时),就会调用reject(内部调用handler)拒绝接受任务。         else if (!addWorker(command, false))             reject(command);     }

AddWorker方法:

  •  创建Worker对象,同时也会实例化一个Thread对象。在创建Worker时会调用threadFactory来创建一个线程。

  •  然后启动这个线程。

2.3.1线程池中CTL属性的作用是什么?

看源码第一反应就是这个CTL到底是个什么东东?有啥用?一番研究得出如下结论:

CTL属性包含两个概念:

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));    private static int ctlOf(int rs, int wc) { return rs | wc; }
  •  runState:即rs 表明当前线程池的状态,是否处于Running,Shutdown,Stop,Tidying。

  •  workerCount:即wc表明当前有效的线程数。

我们点击workerCount即工作状态记录值,以RUNNING为例,RUNNING = -1 << COUNT_BITS;,即-1无符号左移COUNT_BITS位,进一步我们得知COUNT_BITS位29,因为Integer位数为31位(2的五次方减一)

private static final int COUNT_BITS = Integer.SIZE - 3;

既然是29位那么就是Running的值为:

1110 0000 0000 0000 0000 0000 0000 0000   |||  31~29位

那低28位呢,就是记录当前线程的总线数啦:

// Packing and unpacking ctl    private static int runStateOf(int c)     { return c & ~CAPACITY; }    private static int workerCountOf(int c)  { return c & CAPACITY; }    private static int ctlOf(int rs, int wc) { return rs | wc; }

从上述代码可以看到workerCountOf这个函数传入ctl之后,是通过CTL&CAPACITY操作来获取当前运行线程总数的。

也就是RunningState|WorkCount&CAPACITY,算出来的就是低28位的值。因为CAPACITY得到的就是高3位(29-31位)位0,低28位(0-28位)都是1,所以得到的就是ctl中低28位的值。

而runStateOf这个方法的话,算的就是RunningState|WorkCount&CAPACITY,高3位的值,因为CAPACITY是CAPACITY的取反,所以得到的就是高3位(29-31位)为1,低28位(0-28位)为0,所以通过&运算后,所得到的值就是高3为的值。

简单来说就是ctl中是高3位作为状态值,低28位作为线程总数值来进行存储。

2.3.2 shutdownNow和shutdown的区别

看源码发现有两种近乎一样的方法,shutdownNow和shutdown,设计者这么设计自然是有它的道理,那么这两个方法的区别在哪呢?

  •  shutdown会把线程池的状态改为SHUTDOWN,而shutdownNow把当前线程池状态改为STOP。

  •  shutdown只会中断所有空闲的线程,而shutdownNow会中断所有的线程。

  •  shutdown返回方法为空,会将当前任务队列中的所有任务执行完毕;而shutdownNow把任务队列中的所有任务都取出来返回。

2.3.3 线程复用原理

final void runWorker(Worker w) {          Thread wt = Thread.currentThread();          Runnable task = w.firstTask;          w.firstTask = null;          w.unlock(); // allow interrupts          boolean completedAbruptly = true;          try {              while (task != null || (task = getTask()) != null) {                  w.lock();                  // If pool is stopping, ensure thread is interrupted;                  // if not, ensure thread is not interrupted.  This                  // requires a recheck in second case to deal with                  // shutdownNow race while clearing interrupt                  if ((runStateAtLeast(ctl.get(), STOP) ||                       (Thread.interrupted() &&                        runStateAtLeast(ctl.get(), STOP))) &&                      !wt.isInterrupted())                      wt.interrupt();                  try {                      beforeExecute(wt, task);                      Throwable thrown = null;                      try {                          task.run();                      } catch (RuntimeException x) {                          thrown = x; throw x;                      } catch (Error x) {                          thrown = x; throw x;                      } catch (Throwable x) {                          thrown = x; throw new Error(x);                      } finally {                          afterExecute(task, thrown);                      }                  } finally {                      task = null;                      w.completedTasks++;                      w.unlock();                  }              }              completedAbruptly = false;          } finally {              processWorkerExit(w, completedAbruptly);          }      }

就是任务在并不只执行创建时指定的firstTask第一任务,还会从任务队列的中自己主动取任务执行,而且是有或者无时间限定的阻塞等待,以保证线程的存活。

默认的是不允许。

2.4 CountDownLatch和CyclicBarrier区别

countDownLatch是一个计数器,线程完成一个记录一个,计数器递减,只能只用一次。

CyclicBarrier的计数器更像一个阀门,需要所有线程都到达,然后继续执行,计数器递增,提供Reset功能,可以多次使用。

3. 多线程间通信的几种方式

提及多线程又不得不提及多线程通信的机制。首先,要短信线程间通信的模型有两种:共享内存和消息传递,以下方式都是基本这两种模型来实现的。我们来基本一道面试常见的题目来分析:

题目:有两个线程A、B,A线程向一个集合里面依次添加元素"abc"字符串,一共添加十次,当添加到第五次的时候,希望B线程能够收到A线程的通知,然后B线程执行相关的业务操作。

3.1使用volatile关键字

package thread;     public class MyThreadTest {      public static void main(String[] args) throws Exception {          notifyThreadWithVolatile();      }            private static volatile boolean flag = false;            private static void notifyThreadWithVolatile() throws Exception {          Thread thc = new Thread("线程A"){              @Override              public void run() {                  for (int i = 0; i < 10; i++) {                      if (i == 5) {                          flag = true;                          try {                              Thread.sleep(500L);                          } catch (InterruptedException e) {                             // TODO Auto-generated catch block                              e.printStackTrace();                          }                          break;                      }                      System.out.println(Thread.currentThread().getName() + "====" + i);                  }              }          };          Thread thd = new Thread("线程B") {              @Override              public void run() {                  while (true) {                      // 防止伪唤醒 所以使用了while                      while (flag) {                          System.out.println(Thread.currentThread().getName() + "收到通知");                          System.out.println("do something");                          try {                              Thread.sleep(500L);                          } catch (InterruptedException e) {                              // TODO Auto-generated catch block                              e.printStackTrace();                          }                          return ;                      }                  }              }          };          thd.start();          Thread.sleep(1000L);          thc.start();      }  }

感谢各位的阅读,以上就是“怎么快速了解Java多线程”的内容了,经过本文的学习后,相信大家对怎么快速了解Java多线程这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: 怎么快速了解Java多线程

本文链接: https://www.lsjlt.com/news/283926.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么快速了解Java多线程
    这篇文章主要讲解了“怎么快速了解Java多线程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么快速了解Java多线程”吧!线程线程的概念:线程(英语:Thread)是操作系统能够进行运算调...
    99+
    2023-06-16
  • 带你快速搞定java多线程
    目录1、什么是线程2、线程的状态3、怎么通俗理解进程,线程?4、线程和进程的区别5、什么是线程安全6、如何创建线程总结:1、什么是线程 线程是操作系统调度的最小单元,也叫轻量级进程。...
    99+
    2024-04-02
  • 带你快速搞定java多线程(3)
    目录一、锁的概念二、synchronized 的使用方式三、synchronized 的实现原理列小结四、线程池是什么五、为什么要用线程池?六、看下类图,从整体上理解下七、线程池的创...
    99+
    2024-04-02
  • 带你快速搞定java多线程(4)
    目录1、AQS 是什么?2、AQS 模型3、AQS state4、AQS 两种资源共享方式:5、模板方式实现自定义6、锁的分类:公平锁和非公平锁,乐观锁和悲观锁7、CAS8、总结1、...
    99+
    2024-04-02
  • 带你快速搞定java多线程(2)
    目录1、Future的类图结构,从整体上看下Future的结构2、future的使用,说的再多都么什么用,来个例子悄悄怎么用的。3、通俗理解4、原理5、总结1、Future的类图结构...
    99+
    2024-04-02
  • 带你快速搞定java多线程(5)
    目录1、介绍2、countdownlantch的用法。3、如何利用AQS 实现 CountDownLatch4、总结1、介绍 CountDownLantch 倒数计时器,一个同步辅助...
    99+
    2024-04-02
  • 快速了解Java中ThreadLocal类
    最近看Android FrameWork层代码,看到了ThreadLocal这个类,有点儿陌生,就翻了各种相关博客一一拜读;自己随后又研究了一遍源码,发现自己的理解较之前阅读的博文有不同之处,所以决定自己写篇文章说说自己的理解,希望可以起到...
    99+
    2023-05-30
    java threadlocal ava
  • Java多线程怎么理解
    本文小编为大家详细介绍“Java多线程怎么理解”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java多线程怎么理解”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1 线程池的优势总体来说,线程池有如下的优势:(1...
    99+
    2023-07-05
  • 加快Vista中多线程下载速度
    在Windows Vista中,微软为TCP/IP引入了名为“Auto Tuning”的新特性,从理论上说,“Auto Tuning”能够根据网络应用情况调整、优化,从而提...
    99+
    2023-05-23
    多线程 Vista
  • Java嵌入脚本怎么快速解析多层 json
    Java嵌入脚本怎么快速解析多层 json,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。关于Json处理的开源包有很多,比如json-lib、jackson、Gson、Fast...
    99+
    2023-06-03
  • Java多线程通信问题深入了解
    目录概述引入加入线程安全实现生产者与消费者问题总结概述 多线程通信问题,也就是生产者与消费者问题 生产者和消费者为两个线程,两个线程在运行过程中交替睡眠,生产者在生产时消费者没有在消...
    99+
    2024-04-02
  • 新手了解java 多线程基础知识
    目录一、线程的生命周期JDK中用Thread.State类定义了线程的几种状态:二、线程同步1、为什么要有线程同步2、synchronized2.1同步代码块2.2同步方法3、Loc...
    99+
    2024-04-02
  • 怎么快速入门Java编程
    本篇内容主要讲解“怎么快速入门Java编程”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么快速入门Java编程”吧!  自学Java编程的好处是时间自由、经济消耗低,但存在的主要问题是你无法确...
    99+
    2023-06-02
  • Java多线程怎么用
    这篇文章主要介绍了Java多线程怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、概念1.进程1进程:是一个正在进行中的程序,每一个进程执行都有一个执行顺序,该顺序是一...
    99+
    2023-06-17
  • 怎么解析Java多线程程序设计
    小编今天带大家了解怎么解析Java多线程程序设计,文中知识点介绍的非常详细。觉得有帮助的朋友可以跟着小编一起浏览文章的内容,希望能够帮助更多想解决这个问题的朋友找到问题的答案,下面跟着小编一起深入学习“怎么解析Java多线程程序设计”的知识...
    99+
    2023-06-03
  • Java多线程之线程安全问题怎么解决
    本篇内容主要讲解“Java多线程之线程安全问题怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java多线程之线程安全问题怎么解决”吧!1.线程安全概述1.1什么是线程安全问题首先我们需要...
    99+
    2023-06-30
  • 【Java】你掌握了多线程吗?
    【文末送书】今天推荐一本Java多线程编程领域新书《一本书讲透Java线程》 摘要 互联网的每一个角落,无论是大型电商平台的秒杀活动,社交平台的实时消息推送,还是在线视频平台的流量洪峰,背后都离不开多线程技术的支持。在数字化转型的过程中...
    99+
    2023-12-22
    java 开发语言 线程
  • 如何快速了解Java中的IO流
    这篇文章主要介绍“如何快速了解Java中的IO流”,在日常操作中,相信很多人在如何快速了解Java中的IO流问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何快速了解Java中的IO流”的疑惑有所帮助!接下来...
    99+
    2023-06-16
  • 快速了解Java中NIO核心组件
    背景知识同步、异步、阻塞、非阻塞首先,这几个概念非常容易搞混淆,但NIO中又有涉及,所以总结一下。同步:API调用返回时调用者就知道操作的结果如何了(实际读取/写入了多少字节)。异步:相对于同步,API调用返回时调用者不知道操作的结果,后面...
    99+
    2023-05-30
    java nio 组件
  • 你真的了解Java的多线程方法吗
    目录Java 多线程方法详解startrunyieldjoinsleepInterruptdeamonPriority总结Java 多线程方法详解 start start方法&nbs...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作