线上购物网站建设的可行性网站排名按天付费

当前位置: 首页 > news >正文

线上购物网站建设的可行性,网站排名按天付费,某财政局网站建设方案,wordpress英文仿站1. 线程与进程2. 创建和管理线程2.1. 继承Thread类2.2. 实现Runnable接口2.3 利用Callable、FutureTask接口实现。2.4 Thread的常用方法 3. 线程同步3.1. synchronized关键字3.1.1同步代码块#xff1a;3.1.2 同步方法#xff1a; 3.2. Lock接口 4. 线程间通信5. 线程池5.1 使… 1. 线程与进程2. 创建和管理线程2.1. 继承Thread类2.2. 实现Runnable接口2.3 利用Callable、FutureTask接口实现。2.4 Thread的常用方法 3. 线程同步3.1. synchronized关键字3.1.1同步代码块3.1.2 同步方法 3.2. Lock接口 4. 线程间通信5. 线程池5.1 使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象5.2 使用Executors线程池的工具类调用方法返回不同特点的线程池对象 6. Java并发工具类6.1. CountDownLatch6.2. CyclicBarrier6.3. Semaphore6.4. ConcurrentHashMap6.5. BlockingQueue 7. 总结9. 线程优先级10. 守护线程11. 线程局部变量12. 线程异常处理13. 实践建议 Java多线程编程是Java程序员必备的技能之一因为它可以帮助我们编写更高效、更快速的程序。在本文中我们将深入探讨Java多线程的基本概念、线程的创建和管理、同步、线程池以及Java并发工具类。

  1. 线程与进程 进程是操作系统进行资源分配的基本单位它是一个具有一定独立功能的程序关于某个数据集合的一次运行活动它是系统进行资源分配和调度的一个独立单位。 线程是进程中的一个实体它是被操作系统独立调度和执行的基本单位。一个进程中可以有多个线程这些线程共享进程的资源如内存、文件句柄等。线程之间的切换比进程切换要快得多因为线程间通信成本更低。
  2. 创建和管理线程 在Java中有两种方法可以创建线程还有JDK5新增了一种方法实现Callable接口 2.1. 继承Thread类 步骤 ①定义一个子类MyThread继承线程类java.lang.Thread重写run()方法 ②创建MyThread类的对象 ③调用线程对象的start()方法启动线程启动后还是执行run方法的 创建一个新类该类继承自Thread类然后覆盖run方法 class MyThread extends Thread {Overridepublic void run() {// 你的线程代码} }// 在主程序中创建并启动线程 MyThread myThread new MyThread(); myThread.start();优缺点 优点编码简单缺点存在单继承的局限性线程类继承Thread后不能继承其他类不便于扩展 注意 1、为什么不直接调用了run方法而是调用start启动线程。 ​ 直接调用run方法会当成普通方法执行此时相当于还是单线程执行。​ 只有调用start方法才是启动一个新的线程执行。 2、把主线程任务放在子线程之前了。 这样主线程一直是先跑完的相当于是一个单线程的效果了。
    2.2. 实现Runnable接口 步骤 ①定义一个线程任务类MyRunnable实现Runnable接口重写run()方法 ②创建MyRunnable任务对象 ③把MyRunnable任务对象交给Thread处理。 ④调用线程对象的start()方法启动线程 创建一个新类实现Runnable接口然后实现run方法 class MyRunnable implements Runnable {Overridepublic void run() {// 你的线程代码} }// 在主程序中创建并启动线程 Thread thread new Thread(new MyRunnable()); thread.start();实现Runnable接口通常是更好的选择因为它允许你的类继承其他类而Java不支持多继承。 优缺点 优点线程任务类只是实现了Runnale接口可以继续继承类和实现接口扩展性强。缺点编程多一层对象包装如果线程有执行结果是不可以直接返回的。 Thread的构造器 构造器说明public Thread(String name)可以为当前线程指定名称public Thread(Runnable target)封装Runnable对象成为线程对象public Thread(Runnable target String name )封装Runnable对象成为线程对象并指定线程名称 2.3 利用Callable、FutureTask接口实现。 前言 1、前2种线程创建方式都存在一个问题 他们重写的run方法均不能直接返回结果。不适合需要返回线程执行结果的业务场景。 2、怎么解决这个问题呢 JDK 5.0提供了Callable和FutureTask来实现。这种方式的优点是可以得到线程执行的结果。 步骤 ①、得到任务对象 ​ 1.定义类实现Callable接口重写call方法封装要做的事情。 ​ 2.用FutureTask把Callable对象封装成线程任务对象。 ②、把线程任务对象交给Thread处理。 ③、调用Thread的start方法启动线程执行任务 ④、线程执行完毕后、通过FutureTask的get方法去获取任务执行的结果。 FutureTask的API 方法名称说明public FutureTask(Callable call)把Callable对象封装成FutureTask对象。public V get() throws Exception获取线程执行call方法返回的结果。 优缺点 优点线程任务类只是实现接口可以继续继承类和实现接口扩展性强。可以在线程执行完毕后去获取线程执行的结果。缺点编码复杂一点。 总结 方式优点缺点继承Thread类编程比较简单可以直接使用Thread类中的方法扩展性较差不能再继承其他的类不能返回线程执行的结果实现Runnable接口扩展性强实现该接口的同时还可以继承其他的类。编程相对复杂不能返回线程执行的结果实现Callable接口扩展性强实现该接口的同时还可以继承其他的类。可以得到线程执行的结果编程相对复杂 2.4 Thread的常用方法 Thread常用方法获取线程名称getName()、设置名称setName()、获取当前线程对象currentThread()。 当有很多线程在执行的时候我们怎么去区分这些线程呢 此时需要使用Thread的常用方法getName()、setName()、currentThread()等。 Thread获取和设置线程名称 方法名称说明String getName()获取当前线程的名称默认线程名称是Thread-索引void setName(String name)将此线程的名称更改为指定的名称通过构造器也可以设置线程名称 Thread类获得当前线程的对象 方法名称说明public static Thread currentThread()返回对当前正在执行的线程对象的引用 注意 1、此方法是Thread类的静态方法可以直接使用Thread类调用。 2、这个方法是在哪个线程执行中调用的就会得到哪个线程对象。 Thread类的线程休眠方法 方法名称说明public static void sleep(long time)让当前线程休眠指定的时间后再继续执行单位为毫秒。
  3. 线程同步 在多线程环境下如果多个线程同时访问共享资源可能会导致数据不一致的问题。为了解决这个问题我们需要对共享资源进行同步。 线程同步的核心思想 加锁把共享资源进行上锁每次只能一个线程进入访问完毕以后解锁然后其他线程才能进来。 3.1. synchronized关键字 在Java中我们可以使用synchronized关键字来实现同步。synchronized可以修饰方法或者代码块。当一个线程进入synchronized修饰的方法或代码块时其他线程将被阻塞直到该线程离开。 以下是一个使用synchronized关键字的示例 class Counter {private int count;public synchronized void increment() {count;}public synchronized void decrement() {count–;}public synchronized int getCount() {return count;} }3.1.1同步代码块 作用把出现线程安全问题的核心代码给上锁。 原理每次只能一个线程进入执行完毕后自动解锁其他线程才可以进来执行。
    锁对象要求 理论上锁对象只要对于当前同时执行的线程来说是同一个对象即可。 锁对象的规范要求 规范上建议使用共享资源作为锁对象。 对于实例方法建议使用this作为锁对象。 对于静态方法建议使用字节码类名.class对象作为锁对象。 3.1.2 同步方法 作用把出现线程安全问题的核心方法给上锁。 原理每次只能一个线程进入执行完毕以后自动解锁其他线程才可以进来执行。 原理 同步方法其实底层也是有隐式锁对象的只是锁的范围是整个方法代码。如果方法是实例方法同步方法默认用this作为的锁对象。但是代码要高度面向对象如果方法是静态方法同步方法默认用类名.class作为的锁对象。 3.2. Lock接口 除了使用synchronized关键字外Java还提供了java.util.concurrent.locks包中的Lock接口该接口允许我们实现更灵活、更细粒度的同步。ReentrantLock是Lock接口的一个实现它允许线程以可重入的方式获取锁。 以下是一个使用ReentrantLock的示例 import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;class Counter {private int count;private Lock lock new ReentrantLock();public void increment() {lock.lock();try {count;} finally {lock.unlock();}}public void decrement() {lock.lock();try {count–;} finally {lock.unlock();}}public int getCount() {lock.lock();try {return count;} finally {lock.unlock();}} }4. 线程间通信 线程间通信是指多个线程之间互相发送消息或数据的过程。在Java中我们可以使用wait、notify和notifyAll方法实现线程间通信。 线程通信常见形式 通过共享一个数据的方式实现。根据共享数据的情况决定自己该怎么做以及通知其他线程怎么做。 应用场景 生产者与消费者模型生产者线程负责生产数据消费者线程负责消费生产者产生的数据。 要求生产者线程生产完数据后唤醒消费者然后等待自己消费者消费完该数据后唤醒生产者然后等待自己。 方法名称说明void wait()让当前线程等待并释放所占锁直到另一个线程调用notify()方法或 notifyAll()方法void notify()唤醒正在等待的单个线程void notifyAll()唤醒正在等待的所有线程 以下是一个使用wait和notify实现生产者消费者模型的示例 import java.util.LinkedList; import java.util.Queue;public class ProducerConsumerExample {public static void main(String[] args) {QueueInteger queue new LinkedList();int maxSize 10;Thread producer new Thread(new Producer(queue, maxSize), Producer);Thread consumer new Thread(new Consumer(queue), Consumer);producer.start();consumer.start();} }class Producer implements Runnable {private QueueInteger queue;private int maxSize;public Producer(QueueInteger queue, int maxSize) {this.queue queue;this.maxSize maxSize;}Overridepublic void run() {int value 0;while (true) {synchronized (queue) {while (queue.size() maxSize) {try {queue.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Producing value);queue.add(value);queue.notifyAll();}}} }class Consumer implements Runnable {private QueueInteger queue;public Consumer(QueueInteger queue) {this.queue queue;}Overridepublic void run() {while (true) {synchronized (queue) {while (queue.isEmpty()) {try {queue.wait();} catch (InterruptedException e) {e.printStackTrace();}}int value queue.poll();System.out.println(Consuming value);queue.notifyAll();}}} }5. 线程池 线程池是一种管理线程的机制它允许我们重用线程以减少创建和销毁线程的开销。在Java中我们可以使用ExecutorService接口和Executors类来创建和管理线程池。 5.1 使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象 #mermaid-svg-HvdK90SPNP9WMfaR {font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-HvdK90SPNP9WMfaR .error-icon{fill:#552222;}#mermaid-svg-HvdK90SPNP9WMfaR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HvdK90SPNP9WMfaR .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-HvdK90SPNP9WMfaR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HvdK90SPNP9WMfaR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HvdK90SPNP9WMfaR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HvdK90SPNP9WMfaR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HvdK90SPNP9WMfaR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HvdK90SPNP9WMfaR .marker.cross{stroke:#333333;}#mermaid-svg-HvdK90SPNP9WMfaR svg{font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HvdK90SPNP9WMfaR .label{font-family:“trebuchet ms”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-HvdK90SPNP9WMfaR .cluster-label text{fill:#333;}#mermaid-svg-HvdK90SPNP9WMfaR .cluster-label span{color:#333;}#mermaid-svg-HvdK90SPNP9WMfaR .label text,#mermaid-svg-HvdK90SPNP9WMfaR span{fill:#333;color:#333;}#mermaid-svg-HvdK90SPNP9WMfaR .node rect,#mermaid-svg-HvdK90SPNP9WMfaR .node circle,#mermaid-svg-HvdK90SPNP9WMfaR .node ellipse,#mermaid-svg-HvdK90SPNP9WMfaR .node polygon,#mermaid-svg-HvdK90SPNP9WMfaR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HvdK90SPNP9WMfaR .node .label{text-align:center;}#mermaid-svg-HvdK90SPNP9WMfaR .node.clickable{cursor:pointer;}#mermaid-svg-HvdK90SPNP9WMfaR .arrowheadPath{fill:#333333;}#mermaid-svg-HvdK90SPNP9WMfaR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-HvdK90SPNP9WMfaR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-HvdK90SPNP9WMfaR .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-HvdK90SPNP9WMfaR .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-HvdK90SPNP9WMfaR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-HvdK90SPNP9WMfaR .cluster text{fill:#333;}#mermaid-svg-HvdK90SPNP9WMfaR .cluster span{color:#333;}#mermaid-svg-HvdK90SPNP9WMfaR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-HvdK90SPNP9WMfaR :root{–mermaid-font-family:“trebuchet ms”,verdana,arial,sans-serif;} ExecutorService ThreadPoolExecutor ThreadPoolExecutor构造器的参数说明 注 临时线程什么时候创建啊 新任务提交时发现核心线程都在忙任务队列也满了并且还可以创建临时线程此时才会创建临时线程。 什么时候会开始拒绝任务 核心线程和临时线程都在忙任务队列也满了新的任务过来的时候才会开始任务拒绝。 ExecutorService的常用方法 方法名称说明void execute(Runnable command)执行任务/命令没有返回值一般用来执行 Runnable 任务Future submit(Callable task)执行任务返回未来任务对象获取线程结果一般拿来执行 Callable 任务void shutdown()等任务执行完毕后关闭线程池ListRunnable] shutdownNow()立刻关闭停止正在执行的任务并返回队列中未执行的任务 5.2 使用Executors线程池的工具类调用方法返回不同特点的线程池对象 Executors得到线程池对象的常用方法 Executors线程池的工具类通过调用方法返回不同类型的线程池对象。 方法名称说明public static ExecutorService newCachedThreadPool()线程数量随着任务增加而增加如果线程任务执行完毕且空闲了一段时间则会被回收掉。public static ExecutorService newFixedThreadPool(int nThreads)创建固定线程数量的线程池如果某个线程因为执行异常而结束那么线程池会补充一个新线程替代它。public static ExecutorService newSingleThreadExecutor ()创建只有一个线程的线程池对象如果该线程出现异常而结束那么线程池会补充一个新线程。public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)创建一个线程池可以实现在给定的延迟后运行任务或者定期执行任务。 以下是一个使用线程池的示例 import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {ExecutorService executorService Executors.newFixedThreadPool(5);for (int i 0; i 10; i) {Runnable worker new WorkerThread( i);executorService.execute(worker);}executorService.shutdown();while (!executorService.isTerminated()) {}System.out.println(All threads finished);} }class WorkerThread implements Runnable {private String message;public WorkerThread(String message) {this.message message;}Overridepublic void run() {System.out.println(Thread.currentThread().getName() processing message: message);processMessage();}private void processMessage() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}} }6. Java并发工具类 Java并发包java.util.concurrent提供了许多并发工具类它们可以帮助我们简化多线程编程。以下是一些常用的并发工具类 6.1. CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成操作。它包含一个初始计数值任何调用await方法的线程都将被阻塞直到计数值为0。 6.2. CyclicBarrier CyclicBarrier允许一组线程相互等待直到所有线程都到达某个屏障点。当最后一个线程到达屏障点时所有等待的线程将被释放。 6.3. Semaphore Semaphore用于限制可以访问某个资源的线程数量。当一个线程要访问受限资源时需要先获得信号量当线程完成操作时释放信号量。如果没有可用的信号量线程将阻塞直到有线程释放信号量。 6.4. ConcurrentHashMap ConcurrentHashMap是一个线程安全的HashMap实现它允许多个线程并发访问。与使用synchronized关键字的HashMap相比它具有更好的性能。 6.5. BlockingQueue BlockingQueue是一个阻塞队列它支持线程安全的插入和删除操作。当队列为空时删除操作将阻塞当队列满时插入操作将阻塞。BlockingQueue在生产者-消费者模型中非常有用。
  4. 总结 本文深入探讨了Java多线程编程的基本概念、线程的创建和管理、同步、线程池以及Java并发工具类。了解这些概念和技术对于编写高效、高性能的Java程序至关重要。希望本文能为你的Java多线程编程之旅提供有用的指导## 8. 线程的状态和生命周期 在Java中线程具有以下状态 新建New当我们创建了一个线程对象但还没有调用start()方法时线程处于新建状态。就绪Runnable当线程对象调用了start()方法后线程进入就绪状态。在这个状态下线程已经准备好运行等待操作系统分配时间片。运行Running线程获得时间片并开始执行run()方法中的代码时线程处于运行状态。阻塞Blocked线程在等待获取锁以进入同步代码块或方法时线程进入阻塞状态。等待Waiting线程在等待其他线程执行特定操作如调用notify()或notifyAll()方法时线程进入等待状态。例如线程调用了Object.wait()、Thread.join()或LockSupport.park()方法。超时等待Timed Waiting线程在等待其他线程执行特定操作但最多等待指定的时间。例如线程调用了Thread.sleep()、Object.wait(long timeout)或LockSupport.parkNanos()方法。终止Terminated线程完成了run()方法的执行或因异常而终止线程进入终止状态。 要获取线程的当前状态可以调用Thread.getState()方法。
  5. 线程优先级 在Java中线程具有优先级。优先级较高的线程可能会比优先级较低的线程获得更多的执行时间。线程优先级是通过Thread.setPriority(int)方法设置的取值范围为1到10其中1表示最低优先级10表示最高优先级。可以使用Thread.getPriority()方法获取线程的当前优先级。 需要注意的是线程优先级并不能保证线程执行的顺序它只是影响线程获得执行时间的可能性。因此在编写多线程程序时不应依赖线程优先级来实现正确的同步或顺序。
  6. 守护线程 守护线程Daemon Thread是一种特殊类型的线程主要用于在后台为其他线程提供服务。当所有非守护线程结束时守护线程会自动结束。垃圾回收线程就是一个典型的守护线程。 要将线程设置为守护线程可以在调用start()方法之前调用Thread.setDaemon(true)方法。可以使用Thread.isDaemon()方法检查线程是否为守护线程。 注意不要将可能与其他线程进行交互的线程设置为守护线程因为守护线程可能会在任何时候终止。如果守护线程在与其他线程交互时突然终止可能会导致不可预测的行为或数据不一致。
  7. 线程局部变量 线程局部变量Thread-Local Variables是一种特殊类型的变量它为每个线程提供独立的变量副本。这意味着每个线程可以访问和修改它自己的变量副本而不会影响其他线程的副本。 Java中提供了ThreadLocal类来实现线程局部变量。要创建一个线程局部变量可以创建一个ThreadLocal对象并调用get()和set(T value)方法来获取和设置线程的变量副本。以下是一个使用ThreadLocal的示例 public class ThreadLocalExample {private static ThreadLocalInteger threadLocalCounter new ThreadLocalInteger() {Overrideprotected Integer initialValue() {return 0;}};public static void main(String[] args) {Thread t1 new Thread(new Runnable() {Overridepublic void run() {for (int i 0; i 5; i) {int counter threadLocalCounter.get();threadLocalCounter.set(counter 1);System.out.println(Thread-1: threadLocalCounter.get());}}});Thread t2 new Thread(new Runnable() {Overridepublic void run() {for (int i 0; i 5; i) {int counter threadLocalCounter.get();threadLocalCounter.set(counter 1);System.out.println(Thread-2: threadLocalCounter.get());}}});t1.start();t2.start();} }在这个示例中threadLocalCounter是一个线程局部变量。我们为每个线程提供了初始值0。当每个线程执行时它们都会访问和修改自己的计数器副本而不会影响其他线程的副本。
  8. 线程异常处理 当线程抛出未捕获的异常时Java提供了一种机制来处理这些异常。可以通过实现Thread.UncaughtExceptionHandler接口并调用Thread.setDefaultUncaughtExceptionHandler()方法来设置全局的未捕获异常处理器。此外还可以通过调用Thread.setUncaughtExceptionHandler()方法为单个线程设置未捕获异常处理器。 以下是一个设置未捕获异常处理器的示例 public class ThreadExceptionHandlingExample {public static void main(String[] args) {Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {Overridepublic void uncaughtException(Thread t, Throwable e) {System.out.println(t.getName() throws exception: e);}});Thread t1 new Thread(new Runnable() {Overridepublic void run() {System.out.println(1 / 0);}}, Thread-1);Thread t2 new Thread(new Runnable() {Overridepublic void run() {throw new RuntimeException(An exception occurred in Thread-2);}}, Thread-2);t1.start();t2.start();} }在这个示例中我们设置了一个全局的未捕获异常处理器用于处理所有线程抛出的未捕获异常。当Thread-1和Thread-2抛出未捕获的异常时异常处理器会捕获并处理这些异常。
  9. 实践建议 在进行多线程编程时以下是一些建议和注意事项 尽量使用java.util.concurrent包中提供的高级并发工具类而不是直接使用Thread和synchronized关键字。这可以简化代码并提高程序的可维护性和性能。在编写多线程程序时避免使用全局变量或共享状态以降低同步的复杂性和可能出现的错误。要充分利用Java的内存模型确保线程之间正确地共享和同步数据。使用线程池来管理和调度线程以提高程序性能。避免线程优先级来实现正确的同步或顺序因为它不能保证线程执行的顺序。使用守护线程为其他线程提供后台服务但不要将可能与其他线程进行交互的线程设置为守护线程。当需要为每个线程提供独立的变量副本时使用线程局部变量。为线程设置未捕获异常处理器以便在线程抛出未捕获的异常时进行处理。