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

北京网站建设一站式服务WordPress接入广告

北京网站建设一站式服务,WordPress接入广告,wordpress 糗百,中铁建设集团门户网登录网站线程基础 进程与线程 进程:可以被看做是程序的实体, 是系统进行资源分配和调度的基本单位. 线程:是操作系统调度的最小单元, 也叫轻量级进程 使用多线程的优点 可以减少程序的响应时间。如果某个操作很耗时, 能够避免陷入长时间的等待, 从而有着更好的交互性. 线程较之进…线程基础 进程与线程 进程:可以被看做是程序的实体, 是系统进行资源分配和调度的基本单位. 线程:是操作系统调度的最小单元, 也叫轻量级进程 使用多线程的优点 可以减少程序的响应时间。如果某个操作很耗时, 能够避免陷入长时间的等待, 从而有着更好的交互性. 线程较之进程, 创建和切换的开销更小, 在共享数据方面的效率非常高.更高利用多CPU或多核设备的性能 简化程序结构, 便于理解维护. 线程的状态 NewRunnable(可运行状态, 不是立即运行, 取决于系统的决定)Blocked(当调用同步方法而未获取锁时会进入阻塞状态)Waiting(暂时不活动, 不运行任何代码, 消耗最少的资源)Timed waiting(与waiting相比, 能在指定的时间自行返回)Terminated终止状态已经执行完毕或者异常退出 阻塞状态是线程因为某些条件不满足如等待I/O操作或等待获取锁而暂时停止执行直至条件得到满足。处于等待的线程不会尝试获取锁它是在等待其他线程显式地通知或中断才返回到可运行状态。 创建线程 创建线程的方法一般有三种: 继承Thread类, 重写run方法(本质为实现Runnable接口的一个实例) 1.创建继承Thread类的子类, 并重写run方法(执行体). 2.创建子类的实例 3.调用实例对象的start方法启动线程 实现Runnable接口, 并实现接口的run方法 1.自定义一个实现Runnable接口的类, 实现run方法 2.创建上面的类的对象, 并将其作为参数去创建一个Thread子类的实例.Thread mThread new Thread(参数) 3.调用Thread.start(). 实现Callable接口, 重写call方法 是Executor框架中的功能类, 与Runnable接口的功能类似, 但提供了比Runnable更强大的功能, 主要表现在以下3点: 1.任务结束后提供一个返回值, 2.call方法可以抛出异常 3.运行了Callback后可以得到一个Future对象, 该对象利用Future.get方法监视目标线程调用call方法的情况, 但会一直阻塞直到call方法返回结果 进程中断 线程中断是一种协作机制它允许一个线程告知另一个线程希望它停止当前正在做的事情。中断是一种软件协议而不是强迫线程停止的方法。当一个线程中断另一个线程时被中断的线程并不会立即停止运行而是由这个线程决定如何响应中断。 理解线程中断的几个关键点如下 中断标志位每个线程都有一个中断状态它表示线程是否被中断。通过调用线程实例的 interrupt() 方法可以设置这个线程的中断状态。如果线程在执行时没有检查中断状态则调用 interrupt() 不会立刻停止线程。检查中断线程可以通过调用静态方法 Thread.interrupted() 或实例方法 isInterrupted() 来检查它自己是否被中断。Thread.interrupted() 会清除当前线程的中断状态而 isInterrupted() 则不会。响应中断当线程检测到中断请求时可以通过多种方式来响应 完全忽略中断请求这通常不是好的做法因为这会让发送中断的线程很难控制这个线程。清理资源停止当前任务并优雅退出。抛出 InterruptedException这通常发生在线程阻塞操作如 sleep(), wait(), join()中被中断时。在抛出 InterruptedException 之前JVM会先将这个线程的中断状态清除然后抛出异常。 不应该忽视中断一个设计良好的线程任务在检测到中断时应当尽快清理资源保存状态并且合理地结束执行以便程序整体可以正确反应中断请求如停止或重启任务。 class Task implements Runnable {public void run() {while (!Thread.currentThread().isInterrupted()) {// 在这里执行任务工作try {// 假设此处有可能阻塞的操作Thread.sleep(1000);} catch (InterruptedException e) {// 当线程在sleep时被中断会进入这个catch块System.out.println(Thread was interrupted, safely stopping.);break; // 退出循环结束线程的执行}}// 清理资源和状态} }public class InterruptExample {public static void main(String[] args) throws InterruptedException {Thread thread new Thread(new Task());thread.start();// 给线程一些时间来启动并执行任务Thread.sleep(3000);// 发出中断请求thread.interrupt();} }线程同步 同步 Java中的同步指的是通过人为的控制和调度保证共享资源的多线程访问成为线程安全来保证结果的准确。 ReentrantLock重入锁 ReentrantLock定义了一个单独的布尔值标记锁是否被任何线程锁定。如果是则持有锁的线程可以再次获得但必须释放它同样多的次数才能解锁。 class SharedObject {private ReentrantLock lock new ReentrantLock();void sharedMethod() {lock.lock(); // 在访问临界区之前获取锁try {// 临界区只有一个线程在同一时间可以访问// 像这样的代码...} finally {lock.unlock(); //总是在finally块中释放锁}} }关于sleep与wait的不同点: sleep方法没有释放锁而wait方法释放了锁使得其他线程可以使用同步控制块或者方法。waitnotify和notifyAll只能在同步控制方法或者同步控制块里面使用而sleep可以在任何地方使用sleep必须捕获异常而waitnotify和notifyAll不需要捕获异常sleep是线程类Thread的方法导致此线程暂停执行指定时间给执行机会给其他线程但是监控状态依然保持到时后会自动恢复。调用sleep不会释放对象锁。wait是Object类的方法对此对象调用wait方法导致本线程放弃对象锁进入等待此对象的等待锁定池只有针对此对象发出notify方法或notifyAll后本线程才进入对象锁定池准备获得对象锁进入运行状态。 重入锁(ReentrantLock)与条件对象 支持重进入的锁, 表示该锁支持一个线程对锁本身的重复加锁(其他的线程此时不能对该锁加锁) 加锁的次数要和解锁的次数要相同, 否则其他线程对此锁无法加锁 条件对象condition中提供了condition.await()方法(进入阻塞状态并放弃锁)和condition.signalAll()方法(将该条件对象上等待的线程唤醒, 解除阻塞, 这里说明一下并不是立即激活) //对重入锁和条件对象的测试 public class HelloWorld {static ReentrantLock lock new ReentrantLock();static Condition condition lock.newCondition();public static void main(String[] args) throws InterruptedException {lock.lock();new Thread(new SignalThread()).start();System.out.println(主线程等待通知);try {System.out.println(主线程的前try);condition.await(); //释放锁, 等唤醒后需要重新获取锁System.out.println(主线程的后try);} finally {System.out.println(主线程的final);lock.unlock();}System.out.println(主线程恢复运行);}static class SignalThread implements Runnable {Overridepublic void run() {lock.lock();try {System.out.println(子线程的前try);condition.signal();System.out.println(子线程通知);} finally {System.out.println(子线程的final);lock.unlock();}}} }同步方法 使用synchronized修饰的方法叫做同步方法java中每一个对象都有一个锁使用synchronized声明一个方法那么对象的锁将会保护一整个方法使用同步方法是为了防止多个线程在更新相同的资源时导致数据出错。 实例方法锁定当前对象的实例使用this作为锁对象。静态方法锁定当前对象所属的Class对象使用class对象作为锁对象 同步代码块 使用synchronized关键字加上一个锁对象来创建一个执行区域这个区域内的代码在同一时刻只能被一个线程执行。 synchronized(锁对象) {// 需要同步的代码 }锁对象的选择 使用特定对象作为锁对象通常是共享资源或者与共享资源紧密相关的对象。使用当前实例this作为锁对象适用于多个线程访问某个对象实例的同步问题。使用类对象ClassName.class作为锁对象适用于静态方法或者静态资源的同步。 volatile volatile是Java提供的一种特殊的变量类型修饰符主要用于确保多线程环境中共享变量的可见性线程A在修改了本地内存的值后可能还没来得及同步回主内存线程B就已经读取了该变量这时候线程B读取到的就是旧的值也就实现了线程A修改的值对线程B不可见这就是所谓的可见性问题和顺序性。 java内存模型 Java中的堆内存用来存储对象实例堆内存是被所有线程共享的运行时内存区域因此它存在内存可见性的问题。而局部变量、方法定义的参数则不会在线程之间共享它们不会有内存可见性问题也不受内存模型的影响。Java内存模型定义了线程和主存之间的抽象关系线程之间的共享变量存储在主存中每个线程都有一个私有的本地内存本地内存中存储了该线程共享变量的副本。需要注意的是本地内存是Java内存模型的一个抽象概念Java内存模型控制线程之间的通信它决定一个线程对主存共享变量的写入何时对另一个线程可见。Java内存模型的抽象示意图如图所示。 线程A与线程B之间若要通信的话则必须要经历下面两个步骤 (1)线程A把线程A本地内存中更新过的共享变量刷新到主存中去。 (2)线程B到主存中去读取线程A之前已更新过的共享变量。由此可见如果我们执行下面的语句 int i3;执行线程必须先在自己的工作线程中对变量i所在的缓存行进行赋值操作然后再写入主存中而不是直接将数值3写入主存中。 原子性可见性和有序性 原子性 原子性指的是一个或多个操作要么全部执行且在执行过程中不会被任何因素打断要么就全部都不执行。在Java中原子性操作通常是指不可分割的操作比如对基本数据类型除了long和double之外的读取和赋值操作。例如当一个线程正在执行一个原子操作时其他线程不能中断它直到该操作完全完成。synchronized可以帮助确保方法或者代码块在执行时不会被其他线程干扰保证了操作的原子性。 可见性 可见性是指一个线程对共享变量的修改能够及时地被其他线程见到。缺乏可见性时一个线程可能无法看到另一个线程对共享变量所做的修改。在Java中可见性问题通常是通过使用volatile关键字或者同步机制如synchronized或Lock来解决。volatile保证了一个线程修改的变量值对其他线程来说立刻变得可见而synchronized保证了一个线程在访问共享资源时先清空工作内存然后从主内存加载资源。 有序性 有序性是指程序执行的顺序按照代码的先后顺序执行。由于编译器优化处理器可能会对指令进行重排序使得程序执行的顺序与代码书写的顺序不同。在多线程环境中这可能导致严重问题。为了预防指令重排序的问题可以使用volatile关键字或者synchronized关键字。它们都可以提供一定程度的有序性保证。volatile变量规则可以确保对volatile变量的写操作不会和之前的读写操作重排序相似地synchronized可以确保获取和释放monitor会形成一个内存屏障避免指令重排序。 volatile关键字 前面提到的三个特性volatile关键字可以保证可见性一个线程修改了volatile变量的值新值对于其他线程来说是立即可见的以及有序性当一个变量声明为volatile后会有一个“屏障”限制重排序确保在volatile变量写操作之前的所有操作都不会被编译器重排序到写操作之后但是它是不保证原子性的如果由原子性相关需求还是考虑synchronized 使用它有俩个条件 , 即变量真正独立于(不能使用)其他变量和自己以前的值, 即不能自增, 自减, 因为不能保证原子性.没有包含在其他变量的不变式中(两个线程都会通过用于保护不变式的检查导致错误), 比如 [0, 10], 一个线程修改最大值为5, 同时另一个线程修改最小值为6, 此时区间就变成了[6, 5]. 很明显就错了 使用场景 1.状态标志, 使用volatile修饰Boolean类型的变量, 不依赖于程序内的任何其他状态 2.双重检查锁定模式(DCL) 阻塞队列 阻塞队列简介 阻塞队列常用于生产者和消费者的场景生产者是往队列里添加元素的线程消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器而消费者也只从容器里拿元素。一个线程可以从队列中获取元素如果队列为空那么线程会阻塞直到队列中有元素同样地一个线程可以向队列中插入元素如果队列已满那么该线程会阻塞直到队列中有空间。 阻塞队列就是生产者存放元素的容器, 常见的阻塞场景: 1.队列没有数据, 消费者端的所有线程都会自动挂起(阻塞), 直到有数据放入队列,线程被唤醒 2.队列中数据填满了, 生产者端的所有线程都会自动挂起, 直到队列中有空的位置, 线程被唤醒 支持这两种阻塞场景的队列叫做阻塞队列 BlockingQueue的核心方法: 放入数据 offer(anObject): 如果阻塞队列可以容纳, 返回true, 否则返回false, 并且将anObject放入阻塞队列. (本方法不会阻塞当前执行方法的线程)offer(E, long, TimeUnit): 在指定时间内如果不能往队列中添加, 则返回falseput(anObject): 如果阻塞队列没有空间, 则调用此方法的线程被阻断, 直到有空间再继续. 获取数据 poll(time): 在等待的时间内都不能取到排在队列首位的对象就返回null.poll(long, TimeUnit): 在指定时间内不能取出数据, 返回falsetake(): 为空则阻断drainTo(): 取出所有的可用数据对象(还可以指定个数), 可以提高数据获取效率, 无需多次分批加锁. 释放锁 public class ProducerConsumerExample {public static void main(String[] args) {BlockingQueueString queue new LinkedBlockingQueue(10);// 生产者线程Thread producer new Thread(() - {try {queue.put(Product);} catch (InterruptedException e) {Thread.currentThread().interrupt();e.printStackTrace();}});// 消费者线程Thread consumer new Thread(() - {try {String product queue.take();System.out.println(Consumed: product);} catch (InterruptedException e) {e.printStackTrace();}});producer.start();consumer.start();} }java中的阻塞队列 ArrayBlockingQueue: 由数据结构组成的有界阻塞队列LinkedBlockingQueue: 由链表结构组成的有界阻塞队列PriorityBlockingQueue: 支持优先级排序的无界阻塞队列DelayQueue: 使用优先级队列实现的无界阻塞队列SynchronousQueue: 不储存元素的阻塞队列LinkedTransferQueue: 由链表结构组成的无界阻塞队列LinkedBlockingQueue: 由链表结构组成的双向阻塞队列 线程池 ThreadPoolExecutor ThreadPoolExecutor的构造方法 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueRunnable workQueue, ThreadFactory threadFactoryRejectedExecutionHandler handler)corePoolSize 线程池的核心线程数默认情况下核心线程会在线程池中一直存活即使它们处于闲置状态。如果将ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true那么闲置的核心线程在等待新任务到来时会有超时策略这个时间间隔由keepAliveTime所指定当等待时间超过keepAliveTime所指定的时长后核心线程就会被终止。 maximumPoolSize 线程池所能容纳的最大线程数当活动线程数达到这个数值后后续的新任务将会被阻塞。 keepAliveTime 非核心线程闲置时的超时时长超过这个时长非核心线程就会被回收。当ThreadPool-Executor的allowCoreThreadTimeOut属性设置为true时keepAliveTime同样会作用于核心线程。 unit 用于指定keepAliveTime参数的时间单位这是一个枚举常用的有TimeUnit. MILLISECONDS毫秒、TimeUnit.SECONDS秒以及TimeUnit.MINUTES分钟等。 workQueue 线程池中的任务队列通过线程池的execute方法提交的Runnable对象会存储在这个参数中。 threadFactory 线程工厂为线程池提供创建新线程的功能。ThreadFactory是一个接口它只有一个方法Thread newThread(Runnable r)。 RejectedExecutionHandler 饱和策略当任务队列和线程池都满了的时候采取的应对策略有四种拒绝策略 AbortPolicy (默认): 这种策略会直接抛出RejectedExecutionException异常中止任务的执行。这是默认的策略如果没有设置拒绝策略线程池会采用这种策略。CallerRunsPolicy: 这种策略不会抛弃任务也不会抛出异常而是将任务回退给调用者线程来直接执行。这意味着如果线程池无法处理任务那么执行任务的将会是提交任务的线程本身。DiscardPolicy: 这种策略将静默地忽略无法处理的任务不抛出异常也不执行任务。如果应用程序可以容忍任务丢失这种策略会很有用。DiscardOldestPolicy: 这个策略将丢弃队列中最老的一个任务然后尝试提交当前的任务也就是再次提交而不保证一定会执行。这样做至少可以保证新提交的任务被执行。 ThreadPoolExecutor执行任务时大致遵循如下规则 应用程序向线程池提交一个任务。如果当前活跃的线程数小于核心线程数线程池会创建一个新的工作者线程来执行提交的任务。如果核心线程都在忙新任务就会被放入工作队列中等待。如果工作队列已满而且活跃的线程数小于最大线程数限制线程池会创建额外的工作者线程来处理队列中的任务。如果达到了线程数上限新提交的任务将根据饱和策略来处理。 (1)提交任务后线程池先判断线程数是否达到了核心线程数(corePoolSize)。如果未达到核心线程数则创建核心线程处理任务否则就执行下一步操作。 (2)接着线程池判断任务队列是否满了。如果没满则将任务添加到任务队列中否则就执行下一步操作。 (3)这时因为任务队列满了所以线程池就判断线程数是否达到了最大线程数。如果未达到最大线程数则创建非核心线程处理任务否则就执行饱和策略默认会抛出RejectedExecutionException异常。 上面介绍了线程池的处理流程但还不是很直观。下面结合图4-7,我们就能更好地了解线程池的原理了。 总结先核心线程条件不允许任务队列条件不允许非核心线程条件不允许饱和策略这个过程中核心线程会从任务队列中提取任务 线程池种类 FixedThreadPool 通过Executors的newFixedThreadPool方法来创建。它是一种线程数量固定的线程池当线程处于空闲状态时它们并不会被回收除非线程池被关闭了。当所有的线程都处于活动状态时新任务都会处于等待状态直到有线程空闲出来。由于FixedThreadPool只有核心线程并且这些核心线程不会被回收这意味着它能够更加快速地响应外界的请求。newFixedThreadPool方法的实现如下可以发现FixedThreadPool中只有核心线程并且这些核心线程没有超时机制另外任务队列也是没有大小限制的。 public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads,nThreads, 0L,TimeUnit.MILLISECONDS, new LinkedBlockingQueueRunnable()); }CachedThreadPool 通过Executors的newCachedThreadPool方法来创建。它是一种线程数量不定的线程池它只有非核心线程并且其最大线程数为Integer.MAX_VALUE。由于Integer.MAX_VALUE是一个很大的数实际上就相当于最大线程数可以任意大。当线程池中的线程都处于活动状态时线程池会创建新的线程来处理新任务否则就会利用空闲的线程来处理新任务。线程池中的空闲线程都有超时机制这个超时时长为60秒超过60秒闲置线程就会被回收。和FixedThreadPool不同的是CachedThreadPool的任务队列其实相当于一个空集合这将导致任何任务都会立即被执行因为在这种场景下SynchronousQueue是无法插入任务的。SynchronousQueue是一个非常特殊的队列在很多情况下可以把它简单理解为一个无法存储元素的队列由于它在实际中较少使用这里就不深入探讨它了。从CachedThreadPool的特性来看这类线程池比较适合执行大量的耗时较少的任务。当整个线程池都处于闲置状态时线程池中的线程都会超时而被停止这个时候CachedThreadPool之中实际上是没有任何线程的它几乎是不占用任何系统资源的。newCachedThreadPool方法的实现如下所示 public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS, new SynchronousQueueRunnable()); }ScheduledThreadPool 通过Executors的newScheduledThreadPool方法来创建。它的核心线程数量是固定的而非核心线程数是没有限制的并且当非核心线程闲置时会被立即回收。ScheduledThreadPool这类线程池主要用于执行定时任务和具有固定周期的重复任务newScheduledThreadPool方法的实现如下所示。 public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize,Integer.MAX_VALUE,0,NANOSECONDS, new DelayedWorkQueue()); }SingleThreadExecutor 通过Executors的newSingleThreadExecutor方法来创建。这类线程池内部只有一个核心线程它确保所有的任务都在同一个线程中按顺序执行。SingleThreadExecutor的意义在于统一所有的外界任务到一个线程中这使得在这些任务之间不需要处理线程同步的问题。newSingleThreadExecutor方法的实现如下所示。 public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1,1, 0L,TimeUnit.MILLISECONDS, new LinkedBlockingQueueRunnable())); }AsyncTask 这部分内容在前一本书中处理过这里总结一下他的过程 定义AsyncTask首先需要继承AsyncTask类并定义相关的泛型参数以及重写必要的方法例如doInBackground。执行execute方法在UI线程启动AsyncTask时通过执行execute(Params...)方法开始异步操作。该方法内部调用了executeOnExecutor方法并传递sDefaultExecutor作为执行器默认情况下这是一个串行执行的线程池。状态检查与预操作AsyncTask首次执行前会检查其状态。如果任务尚未执行PENDING状态那么设置其状态为RUNNING并调用onPreExecute()方法来进行初始化操作。任务封装与线程池调用传递给execute方法的参数会被封装成FutureTask对象提交给Executor例如SerialExecutor或THREAD_POOL_EXECUTOR来执行。执行doInBackground方法在工作线程中doInBackground(Params...)方法被执行该方法负责处理后台计算其返回值会作为结果传递给onPostExecute方法。结果的消息传递doInBackground方法的结果会被封装在Message中并通过Handler发送到主线程处理。这个Handler在AsyncTask类加载时已初始化在主线程以确保消息能够被主线程接收和处理。结果处理在UI线程中Handler会接收到包含结果的Message并根据消息的类型调用onPostExecute或onProgressUpdate方法。任务完成在onPostExecute方法中进行UI更新等操作。如果任务在执行中被取消则onCancelled方法会被调用。
http://www.hkea.cn/news/14522420/

相关文章:

  • 大竹网站建设网站设计建设 公司
  • 哪做网站便宜wordpress 分类文章置顶
  • 网站建设 服务内容 费用杭州萧山区专门做网站的公司
  • 网站怎么做百度认证湛江市律师网站建设品牌
  • 廊坊网站建设-纵横网络+网站做网站需要什么东西
  • 工业皮带怎么做免费的网站商业空间设计图片
  • 网站流量不够找人做网站属于了解些什么呢
  • 免费网站知乎怎么利用代码做网站
  • 北京微信网站设计logo多少钱
  • 关于网站建设管理的通知赤峰网站制作
  • 合肥网站建设搜王道下拉网站接口设置
  • cadisen卡迪森手表网站太原企业建站程序
  • 电子商务网站建设与规划视频甘肃临夏州建设局网站
  • 网站建设有哪些平台亦庄附近的网站建设公司
  • 大连网站建设选高合科技网站快速被收录
  • 新网站如何推广公司推广宣传文案
  • 石基网站建设在阿里巴巴上做网站有效果吗
  • 网站开发公司目前主营业务网站弹窗公告代码
  • 魏县网站建设推广中国建设银行官网网址多少
  • 网站建设客户seo网站推广策略
  • 公司刚成立网站怎么做苏州模板网站专业设计
  • 南京建设网站需要多少钱开发微信小程序多少钱
  • 用域名和主机做网站的详细过程专业管网建设服务
  • 先建网站还是先做网页吐鲁番好网站建设设计
  • 怎么优化网站性能线下推广引流渠道
  • 如何注册网站怎么注册做网站分辨率多少
  • 下载中国建设银行官网站网站建设都用哪个好
  • 排名轻松seo 网站wordpress漏洞
  • 高校思政教育工作网站建设年度关键词
  • 网站建设注意哪些事项濮阳做网站优化