精华内容
下载资源
问答
  • 什么是线程?如何实现多线程

    万次阅读 多人点赞 2019-04-09 09:53:36
    【转】什么是线程安全?怎么实现线程安全?什么是进程?什么是线程什么是线程安全?添加一个状态呢?如何确保线程安全?synchronizedlock 转自:https://blog.csdn.net/csdnnews/article/details/82321777 什么是...


    转自: https://blog.csdn.net/csdnnews/article/details/82321777

    什么是进程?

    电脑中时会有很多单独运行的程序,每个程序有一个独立的进程,而进程之间是相互独立存在的。比如下图中的QQ、酷狗播放器、电脑管家等等。在这里插入图片描述

    什么是线程?

    进程想要执行任务就需要依赖线程。换句话说,就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程。

    那什么是多线程?提到多线程这里要说两个概念,就是串行和并行,搞清楚这个,我们才能更好地理解多线程。

    所谓串行,其实是相对于单条线程来执行多个任务来说的,我们就拿下载文件来举个例子:当我们下载多个文件时,在串行中它是按照一定的顺序去进行下载的,也就是说,必须等下载完A之后才能开始下载B,它们在时间上是不可能发生重叠的。
    在这里插入图片描述
    并行:下载多个文件,开启多条线程,多个文件同时进行下载,这里是严格意义上的,在同一时刻发生的,并行在时间上是重叠的。
    在这里插入图片描述
    了解了这两个概念之后,我们再来说说什么是多线程。举个例子,我们打开腾讯管家,腾讯管家本身就是一个程序,也就是说它就是一个进程,它里面有很多的功能,我们可以看下图,能查杀病毒、清理垃圾、电脑加速等众多功能。

    按照单线程来说,无论你想要清理垃圾、还是要病毒查杀,那么你必须先做完其中的一件事,才能做下一件事,这里面是有一个执行顺序的。

    如果是多线程的话,我们其实在清理垃圾的时候,还可以进行查杀病毒、电脑加速等等其他的操作,这个是严格意义上的同一时刻发生的,没有执行上的先后顺序。
    在这里插入图片描述
    以上就是,一个进程运行时产生了多个线程。

    在了解完这个问题后,我们又需要去了解一个使用多线程不得不考虑的问题——线程安全。

    今天我们不说如何保证一个线程的安全,我们聊聊什么是线程安全?因为我之前面试被问到了,说真的,我之前真的不是特别了解这个问题,我们好像只学了如何确保一个线程安全,却不知道所谓的安全到底是什么!

    什么是线程安全?

    当多个线程访问某个方法时,不管你通过怎样的调用方式、或者说这些线程如何交替地执行,我们在主程序中不需要去做任何的同步,这个类的结果行为都是我们设想的正确行为,那么我们就可以说这个类是线程安全的。
    既然是线程安全问题,那么毫无疑问,所有的隐患都是在多个线程访问的情况下产生的,也就是我们要确保在多条线程访问的时候,我们的程序还能按照我们预期的行为去执行,我们看一下下面的代码。

    Integer count = 0;
    public void getCount() {
           count ++;
           System.out.println(count);
     }
    

    很简单的一段代码,下面我们就来统计一下这个方法的访问次数,多个线程同时访问会不会出现什么问题,我开启的3条线程,每个线程循环10次,得到以下结果:
    在这里插入图片描述

    我们可以看到,这里出现了两个26,出现这种情况显然表明这个方法根本就不是线程安全的,出现这种问题的原因有很多。

    最常见的一种,就是我们A线程在进入方法后,拿到了count的值,刚把这个值读取出来,还没有改变count的值的时候,结果线程B也进来的,那么导致线程A和线程B拿到的count值是一样的。

    那么由此我们可以了解到,这确实不是一个线程安全的类,因为他们都需要操作这个共享的变量。其实要对线程安全问题给出一个明确的定义,还是蛮复杂的,我们根据我们这个程序来总结下什么是线程安全。

    当多个线程访问某个方法时,不管你通过怎样的调用方式、或者说这些线程如何交替地执行,我们在主程序中不需要去做任何的同步,这个类的结果行为都是我们设想的正确行为,那么我们就可以说这个类是线程安全的。

    搞清楚了什么是线程安全,接下来我们看看Java中确保线程安全最常用的两种方式。先来看段代码。

    public void threadMethod(int j) {
    
        int i = 1;
    
        j = j + i;
    }
    
    

    大家觉得这段代码是线程安全的吗?

    毫无疑问,它绝对是线程安全的,我们来分析一下,为什么它是线程安全的?

    我们可以看到这段代码是没有任何状态的,就是说我们这段代码,不包含任何的作用域,也没有去引用其他类中的域进行引用,它所执行的作用范围与执行结果只存在它这条线程的局部变量中,并且只能由正在执行的线程进行访问。当前线程的访问,不会对另一个访问同一个方法的线程造成任何的影响。

    两个线程同时访问这个方法,因为没有共享的数据,所以他们之间的行为,并不会影响其他线程的操作和结果,所以说无状态的对象,也是线程安全的。

    添加一个状态呢?

    如果我们给这段代码添加一个状态,添加一个count,来记录这个方法并命中的次数,每请求一次count+1,那么这个时候这个线程还是安全的吗?

    public class ThreadDemo {
    
       int count = 0; // 记录方法的命中次数
    
       public void threadMethod(int j) {
    
           count++ ;
    
           int i = 1;
    
           j = j + i;
       }
    }
    
    

    明显已经不是了,单线程运行起来确实是没有任何问题的,但是当出现多条线程并发访问这个方法的时候,问题就出现了,我们先来分析下count+1这个操作。

    进入这个方法之后首先要读取count的值,然后修改count的值,最后才把这把值赋值给count,总共包含了三步过程:“读取”一>“修改”一>“赋值”,既然这个过程是分步的,那么我们先来看下面这张图,看看你能不能看出问题:
    在这里插入图片描述
    可以发现,count的值并不是正确的结果,当线程A读取到count的值,但是还没有进行修改的时候,线程B已经进来了,然后线程B读取到的还是count为1的值,正因为如此所以我们的count值已经出现了偏差,那么这样的程序放在我们的代码中,是存在很多的隐患的。

    如何确保线程安全?

    既然存在线程安全的问题,那么肯定得想办法解决这个问题,怎么解决?我们说说常见的几种方式

    synchronized

    synchronized关键字,就是用来控制线程同步的,保证我们的线程在多线程环境下,不被多个线程同时执行,确保我们数据的完整性,使用方法一般是加在方法上。

    public class ThreadDemo {
    
       int count = 0; // 记录方法的命中次数
    
       public synchronized void threadMethod(int j) {
    
           count++ ;
    
           int i = 1;
    
           j = j + i;
       }
    }
    
    

    这样就可以确保我们的线程同步了,同时这里需要注意一个大家平时忽略的问题,首先synchronized锁的是括号里的对象,而不是代码,其次,对于非静态的synchronized方法,锁的是对象本身也就是this。

    当synchronized锁住一个对象之后,别的线程如果想要获取锁对象,那么就必须等这个线程执行完释放锁对象之后才可以,否则一直处于等待状态。

    注意点:虽然加synchronized关键字,可以让我们的线程变得安全,但是我们在用的时候,也要注意缩小synchronized的使用范围,如果随意使用时很影响程序的性能,别的对象想拿到锁,结果你没用锁还一直把锁占用,这样就有点浪费资源。

    lock

    先来说说它跟synchronized有什么区别吧,Lock是在Java1.6被引入进来的,Lock的引入让锁有了可操作性,什么意思?就是我们在需要的时候去手动的获取锁和释放锁,甚至我们还可以中断获取以及超时获取的同步特性,但是从使用上说Lock明显没有synchronized使用起来方便快捷。我们先来看下一般是如何使用的:

    private Lock lock = new ReentrantLock(); // ReentrantLock是Lock的子类
    
       private void method(Thread thread){
           lock.lock(); // 获取锁对象
           try {
               System.out.println("线程名:"+thread.getName() + "获得了锁");
               // Thread.sleep(2000);
           }catch(Exception e){
               e.printStackTrace();
           } finally {
               System.out.println("线程名:"+thread.getName() + "释放了锁");
               lock.unlock(); // 释放锁对象
           }
       }
    
    

    进入方法我们首先要获取到锁,然后去执行我们业务代码,这里跟synchronized不同的是,Lock获取的所对象需要我们亲自去进行释放,为了防止我们代码出现异常,所以我们的释放锁操作放在finally中,因为finally中的代码无论如何都是会执行的。

    写个主方法,开启两个线程测试一下我们的程序是否正常:

    public static void main(String[] args) {
           LockTest lockTest = new LockTest();
    
           // 线程1
           Thread t1 = new Thread(new Runnable() {
    
               @Override
               public void run() {
                   // Thread.currentThread()  返回当前线程的引用
                   lockTest.method(Thread.currentThread());
               }
           }, "t1");
    
           // 线程2
           Thread t2 = new Thread(new Runnable() {
    
               @Override
               public void run() {
                   lockTest.method(Thread.currentThread());
               }
           }, "t2");
    
           t1.start();
           t2.start();
       }
    
    

    结果
    在这里插入图片描述
    可以看出我们的执行,是没有任何问题的。

    其实在Lock还有几种获取锁的方式,我们这里再说一种,就是tryLock()这个方法跟Lock()是有区别的,Lock在获取锁的时候,如果拿不到锁,就一直处于等待状态,直到拿到锁,但是tryLock()却不是这样的,tryLock是有一个Boolean的返回值的,如果没有拿到锁,直接返回false,停止等待,它不会像Lock()那样去一直等待获取锁。

    我们来看下代码:

    private void method(Thread thread){
           // lock.lock(); // 获取锁对象
           if (lock.tryLock()) {
               try {
                   System.out.println("线程名:"+thread.getName() + "获得了锁");
                   // Thread.sleep(2000);
               }catch(Exception e){
                   e.printStackTrace();
               } finally {
                   System.out.println("线程名:"+thread.getName() + "释放了锁");
                   lock.unlock(); // 释放锁对象
               }
           }
       }
    
    

    结果:我们继续使用刚才的两个线程进行测试可以发现,在线程t1获取到锁之后,线程t2立马进来,然后发现锁已经被占用,那么这个时候它也不在继续等待。

    在这里插入图片描述
    似乎这种方法,感觉不是很完美,如果我第一个线程,拿到锁的时间,比第二个线程进来的时间还要长,是不是也拿不到锁对象?

    那我能不能,用一中方式来控制一下,让后面等待的线程,可以等待5秒,如果5秒之后,还获取不到锁,那么就停止等,其实tryLock()是可以进行设置等待的相应时间的。

    private void method(Thread thread) throws InterruptedException {
           // lock.lock(); // 获取锁对象
    
           // 如果2秒内获取不到锁对象,那就不再等待
           if (lock.tryLock(2,TimeUnit.SECONDS)) {
               try {
                   System.out.println("线程名:"+thread.getName() + "获得了锁");
    
                   // 这里睡眠3秒
                   Thread.sleep(3000);
               }catch(Exception e){
                   e.printStackTrace();
               } finally {
                   System.out.println("线程名:"+thread.getName() + "释放了锁");
                   lock.unlock(); // 释放锁对象
               }
           }
       }
    
    

    结果:看上面的代码,我们可以发现,虽然我们获取锁对象的时候,可以等待2秒,但是我们线程t1在获取锁对象之后,执行任务缺花费了3秒,那么这个时候线程t2是不在等待的。
    在这里插入图片描述
    我们再来改一下这个等待时间,改为5秒,再来看下结果:

    private void method(Thread thread) throws InterruptedException {
           // lock.lock(); // 获取锁对象
    
           // 如果5秒内获取不到锁对象,那就不再等待
           if (lock.tryLock(5,TimeUnit.SECONDS)) {
               try {
                   System.out.println("线程名:"+thread.getName() + "获得了锁");
               }catch(Exception e){
                   e.printStackTrace();
               } finally {
                   System.out.println("线程名:"+thread.getName() + "释放了锁");
                   lock.unlock(); // 释放锁对象
               }
           }
       }
    
    

    结果:这个时候我们可以看到,线程t2等到5秒获取到了锁对象,执行了任务代码。
    在这里插入图片描述
    以上就是使用Lock,来保证我们线程安全的方式。

    展开全文
  • 什么是线程调度?

    千次阅读 2019-09-18 02:37:37
    线程调度有两种: 1.分时调度 分时调度就是所有线程轮流拥有(使用)cpu的使用权,平均分配每个线程占用cpu的时间 2.抢占式调度 抢占式调度就是优先让优先级高的线程使用cpu,如果线程的优先级相同,则会随机选择一个,...

    计算机通常只有一个CPU,在任意时刻只能执行一条机器指令,每个线程只有获得CPU的使用权才能执行指令。所谓多线程的并发运行,其实是指从宏观上看,各个线程轮流获得CPU的使用权,分别执行各自的任务。在线程池中,会有多个处于就绪状态的线程在等待CPU,JAVA虚拟机的一项任务就是负责线程的调度,线程调度是指按照特定机制为多个线程分配CPU的使用权。

    线程调度有两种:
    1.分时调度
    分时调度就是所有线程轮流拥有(使用)cpu的使用权,平均分配每个线程占用cpu的时间
    2.抢占式调度
    抢占式调度就是优先让优先级高的线程使用cpu,如果线程的优先级相同,则会随机选择一个,所以谁的优先级高,谁抢夺cpu的几率就越大,从而优先级高的占用cpu的时间会更长,Java为抢占式调度.
    抢占式调度使cpu会在多个进程中、多个线程中来回跳转,其速度非常快:1/n毫秒,
    比方说现在的cpu跳转到迅雷这个进程中,正在执行迅雷中的3个下载任务,如果cpu分配给迅雷这个进程的时间为7毫秒,下载寻龙诀这个任务的线程优先等级比其他两个任务的优先等级要高,则寻龙诀线程所占用的cpu时间则为3秒,其它两个任务的线程则平均为2秒.
    多线程不会增加CPU的速度,但会增加CPU的效率,现在的程序时间大多花在读取数据上,真正的计算工作花时间还是相对少的,因此CPU很大时间表现都很闲,就像挖土效率高,运土效率低。多线程就是要充分利用它的挖土效率,多几个运土车而尽量减少挖土机的休息时间。
    在这里插入图片描述

    展开全文
  • 线程下载,下载进度,下载中数据,已下载数据多线程下载,下载进度,下载中数据,已下载数据多线程下载,下载进度,下载中数据,已下载数据多线程下载,下载进度,下载中数据,已下载数据多线程下载,下载进度,下载中数据,已...
  • 理解什么是线程安全性、原子性

    万次阅读 2019-12-29 11:56:30
    目录 •写在前面 •原子性 ...所谓串行其实是相对于单条线程来执行多个任务来说的,我们就拿下载文件来举个例子,我们下载多个文件,在串行中它是按照一定的顺序去进行下载的,也就是说必须等下载完A...

    目录

    •写在前面

    •原子性

    加锁机制


    •写在前面

    进程想要执行任务需要依赖线程,换句话说就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程。提到多线程这里要说两个概念,就是串行和并行,搞清楚这个我们才能更好的理解多线程。所谓串行其实是相对于单条线程来执行多个任务来说的,我们就拿下载文件来举个例子,我们下载多个文件,在串行中它是按照一定的顺序去进行下载的,也就是说必须等下载完A之后,才能开始下载B,它们在时间上是不可能发生重叠的。

    要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对共享的和可变的状态的访问。要是的对象是线程安全的,需要采用同步机制来协同对对象可变状态的访问,如果无法实现协同,那么可能会导致数据破坏以及其他不该出现的结果。java中的同步机制是关键字synchronized,它提供了独占式的加锁方式,不仅如此还包括volatile类型变量,显式锁Lock以及原子变量。

    单线程近似定义为“所见即所知”,那么定义线程安全性,则当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么就称这个类是线程安全的。一个类在单线程中运行都不正确,那么它肯定是不会是线程安全的。如果正确的实现了某个对象,那么在任何操作中(包括调用对象的公有方法或者对其公有域进行读写操作)都不会违背不变性条件或后验条件。在线程安全类的对象实例上执行的任何串行或并行操作都不会处于无效状态。

    无状态的对象一定是安全的,啥是无状态?这个类既不包括任何域,也不包括任何对其他类中域的引用。举个例子,大多数Servlet都是无状态的,从而极大的降低了在实现Servlet线程安全性时的复杂性,只有当Servlet在处理请求时需要保存一些信息,线程安全性才会成为一个问题。

    •原子性

    其实原子性就是一个不可分割的,我们怎么理解呢?举个例子,当我们在无状态对象中增加一个状态时,会发生什么情况?比我们要计算一个类调用了多少次(这个类可以是Servlet),我们定义一个私有的Long类型的域(命名为count),在方法中没调用一次就将这个值加一(即count++),如下。

       Integer count = 0;
       public void getCount() {
           count ++;
           System.out.println(count);
       }

    由于我们没有对这个类进行任何的同步机制操作,所以这个类是非线程安全的,虽然在单线程环境中能正确运行,但在多线程情况下就会出现问题。我们注意到count++这个操作,这个操作看上去是一个操作,其实这个操作并非原子性的,因为它并不会作为一个不可分割的操作来执行,实际上count++ 包含了三个独立的操作,分为读取count的值,将值加1,然后计算结构写入count中,这是一个“读取-修改-写入”的操作序列,并且其结果依赖于之前的状态。在并发下就会出现问题,我再多线程下跑了上面那段代码,结果如下

    我们可以看到,这里出现了两个26,为什么会出现这种情况,出现这种情况显然表明我们这个方法根本就不是线程安全的,出现这种问题的原因有很多,我们说最常见的一种,就是我们A线程在进入方法后,拿到了count的值,刚把这个值读取出来还没有改变count的值的时候,结果线程B也进来的,那么导致线程A和线程B拿到的count值是一样的。

    在并发编程中,这种由于不恰当的执行时序而出现不正确的结果是一种非常重要的情况,它有一个正式的名字,叫“竞态条件”。竞态条件是啥?当某个计算的正确性取决于多个线程的交替执行时序时,那么就会发生竞态条件,最常见的竞态条件类型就是“先检查后执行”操作,即通过一个可能失效的观察结果来决定下一步的动作。比如首先观察到某个条件为真(例如文件X不存在),然后根据这个观察结果采用相应的动作(创建文件X),但事实上,在你观察到这个结果以及开始创建文件之间,观察结果可能变得无效(另一个线程在这个期间创建了文件X),从而导致各种问题(未预期的异常、数据覆盖、文件被破坏等)。

    与大多数并发错误一样,竞态条件并不总是会产生错误,还需要某种不恰当的执行时序。原子操作是对于访问同一个状态的所有操作(包括该操作本身)来说,这个操作是一个以原子方式执行的操作。而我们前面提到的类似count++的这种操作,叫做复合操作,即包含了一组必须以原子方式执行的操作以确保线程安全性。在实际情况中,应该尽可能的使用现有的线程安全对象来管理类的状态,与非线程安全的对象相比,判断线程安全对象的可能状态及其状态转换情况要更为容易,从而也更容易维护和验证线程安全性。这里值得一提的是,java中给我们弄好了很多原子操作的类型,在这个包下java.util.concurrent.atomic。

    加锁机制

    上面我们说了,我们可以对单个类进行原子性操作,这样可以保证我们程序的安全性,但是,我们想一想,如果当多个原子性的操作同时进行时,而且各个原子性操作之间都存在相互依赖的关系,这种情况下,我们怎么保证程序运行正确(线程安全)?如果还是使用原子性操作的方法,那么我们要保持状态的一致性,就需要在单个原子操作中更新所有相关的状态变量。

    说到这里,我们就不得不提一下java提供的一种内置的锁机制来支持原子性,即同步代码块(synchronized block),同步代码快包括两部分,一个作为锁的对象引用,一个作为由这个锁保护的代码块。以关键字synchronized来修饰的方法就是一种横跨整个方法体的同步代码块,其中该同步代码块的锁就是方法调用所在的对象。每个Java对象都可以用作一个实现同步的锁,这些所被称为内置锁或监视器锁。线程在进入同步代码块之前会自动获得锁,并且在退出同步代码块时自动释放锁,这里要说,获得内置锁的唯一途径就是进入由这个锁保护的同步代码块或方法。值得一提的是,内置锁相当于一种互斥锁,意味着最多只有一个线程能持有这种锁。要注意了,任何一个执行同步代码块的线程,都不能看到有其他线程正在执行由同一锁保护的同步代码块(这里涉及到可见性的问题)。synchronized直接加在方法上,虽然能很方便的解决线程安全的问题,但是也会带来性能低下的问题,所以synchronized怎么使用,也是值得学习的。

    可重入函数可以由多于一个任务并发使用,而不必担心数据错误。相反,不可重入函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关键部分禁用中断)。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据。可重入函数要么使用本地变量,要么在使用全局变量时保护自己的数据。

    当某个线程请求一个由其他线程持有的锁时,发出请求的线程就会被阻塞,然而,由于内置锁是可重入的,因此如果某个线程试图获得一个已经由它自己持有的锁,那么这个请求就会成功。“重入”意味着获取锁的操作的粒度是线程,而不是调用。重入的一种实现方式是,为每一个锁关联一个获取计数值和一个所有者线程,当计数值为0时,这个锁就被认为是没有被任何线程持有。当线程请求一个未被持有的锁时,JVM将记下锁的持有者,并且将获取计数值置为1,如果同一个线程再次请求获取这个锁,计数值将递增,而当线程退出同步代码块时,计数器会相应的递减,当计数值为0时,这个锁将被释放。

    到此我们就可以将多个复合操作封装到一个同步代码块中,但是这样是不够的,如果用同步代码块来协调对某个变量的访问,那么在访问这个变量的所有位置上都需要使用同步。而且,当使用锁来协调对某个变量的访问是,在访问变量的所有位置上都要使用同一个锁。而且,并不是只有在写入共享变量时才需要使用同步,对于可能被多个线程同时访问的可变状态变量,在访问它时都需要有同一个锁,这种情况下,我们成状态变量时由这个锁保护的。

    在这里值得一提的是,当使用锁时,你应该清楚代码块中实现的功能,以及在执行该代码块时是否需要很长的时间。无论是执行计算密集的操作,还是在执行某个可能阻塞的操作,如果持有锁的时间过长,那么都会带来活跃性或性能的问题。当执行时间较长的计算或者可能无法快速完成的操作时(例如网络IO或控制台IO),一定不要持有锁。

    展开全文
  • 什么是线程阻塞?为什么会出现线程阻塞?

    万次阅读 多人点赞 2019-02-14 22:20:01
    什么是线程阻塞? 在某一时刻某一个线程在运行一段代码的时候,这时候另一个线程也需要运行,但是在运行过程中的那个线程执行完成之前,另一个线程是无法获取到CPU执行权的(调用sleep方法是进入到睡眠暂停状态,...

    什么是线程阻塞?

    在某一时刻某一个线程在运行一段代码的时候,这时候另一个线程也需要运行,但是在运行过程中的那个线程执行完成之前,另一个线程是无法获取到CPU执行权的(调用sleep方法是进入到睡眠暂停状态,但是CPU执行权并没有交出去,而调用wait方法则是将CPU执行权交给另一个线程),这个时候就会造成线程阻塞。

    为什么会出现线程阻塞?

    1.睡眠状态:当一个线程执行代码的时候调用了sleep方法后,线程处于睡眠状态,需要设置一个睡眠时间,此时有其他线程需要执行时就会造成线程阻塞,而且sleep方法被调用之后,线程不会释放锁对象,也就是说锁还在该线程手里,CPU执行权还在自己手里,等睡眠时间一过,该线程就会进入就绪状态,典型的“占着茅坑不拉屎”;

    2.等待状态:当一个线程正在运行时,调用了wait方法,此时该线程需要交出CPU执行权,也就是将锁释放出去,交给另一个线程,该线程进入等待状态,但与睡眠状态不一样的是,进入等待状态的线程不需要设置睡眠时间,但是需要执行notify方法或者notifyall方法来对其唤醒,自己是不会主动醒来的,等被唤醒之后,该线程也会进入就绪状态,但是进入仅需状态的该线程手里是没有执行权的,也就是没有锁,而睡眠状态的线程一旦苏醒,进入就绪状态时是自己还拿着锁的。等待状态的线程苏醒后,就是典型的“物是人非,大权旁落“;

    3.礼让状态:当一个线程正在运行时,调用了yield方法之后,该线程会将执行权礼让给同等级的线程或者比它高一级的线程优先执行,此时该线程有可能只执行了一部分而此时把执行权礼让给了其他线程,这个时候也会进入阻塞状态,但是该线程会随时可能又被分配到执行权,这就很”中国化的线程“了,比较讲究谦让;

    4.自闭状态:当一个线程正在运行时,调用了一个join方法,此时该线程会进入阻塞状态,另一个线程会运行,直到运行结束后,原线程才会进入就绪状态。这个比较像是”走后门“,本来该先把你的事情解决完了再解决后边的人的事情,但是这时候有走后门的人,那就会停止给你解决,而优先把走后门的人事情解决了;

    5.suspend() 和 resume() :这两个方法是配套使用的,suspend() 是让线程进入阻塞状态,它的解药就是resume(),没有resume()它自己是不会恢复的,由于这种比较容易出现死锁现象,所以jdk1.5之后就已经被废除了,这对就是相爱相杀的一对。

    展开全文
  • 到底什么是线程安全

    千次阅读 2018-09-16 12:24:50
    说到线程,想必肯定是离不开对于进程的介绍,进程是程序的一次执行,而什么是线程线程可以理解为进程中的执行的一段程序片段。在一个多任务环境中下面的概念可以帮助我们理解两者间的差别:进程间是独立的,这表现...
  • 什么是线程线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的, 即不同的线程可以执行同样的函数。 什么是线程? 多线程是指程序中包含多个执行流,即在一个...
  •  多个线程同时去下载一个资源,肯定比一个线程下载一个资源速度快的多,所以现在我们要实现一下多个线程下载一个资源,而断点下载意思是,如果上一次因为某种原因,下载没有进行到底,再进行下一次下载的时候...
  • 对此,大家不得不使用第三方的下载工具,例如迅雷、IDM 等支持多线程下载下载软件,来提高下载速度。 Chrome 的下载速度有时候很令人抓狂 第三方工具并非不好,但用起来使用没有自带功能来得舒畅。怎么才能...
  • 所谓断点下载,就是把下载的进度记录下来,当下次继续下载的时候,就读取上一次记录的位置开始继续下载.
  • 线程下载的原理和基本用法

    千次阅读 多人点赞 2017-05-15 23:12:22
    线程可以通俗的理解为下载的通道,一个线程就是文件下载的一个通道,多线程就是同时打开了多个通道对文件进行下载。当服务器提供下载服务时,用户之间共享带宽。本文介绍了多线程下载的原理和基本用法。
  • 什么是线程和多进程

    千次阅读 2014-08-07 13:32:35
    线程和进程都是现在电脑概念里比较时髦的用语,什么是线程什么是多进程?本文详细的给您介绍一下,希望能增进您对当代电脑技术的了解,有不到之 处,还往高手予以更正。进程(英语:Process,中国大陆译作进程,...
  • android多线程下载

    千次阅读 2018-09-28 15:50:37
    (2)当拿到需要进行多线程下载的数据时,根据content-length来确定各个子线程分段请求区域 private void processDownload (String url, long length, DownloadCallback callback) { //100 2 50 0-49 50-99...
  • 今天用java写的多线程下载报错,找了很久,发现是第一次请求服务器时响应码正常,开启多线程部分的响应码为416,响应码对应的意思可以去这里看看点击打开链接。主要意思就是public void setRequestProperty (String...
  • Http多线程下载文件的处理机制

    千次阅读 2017-03-15 00:21:45
    2.Android多线程下载的原理. 3.Android上面进行Http请求下载的需要解决的一些问题.1.http关于下载方面的一些字段(1)Transfer-Encoding (2)content-length (3)rangeTransfer-EncodingTransfer-Encoding,是一个HTTP...
  • Java_java多线程下载-断点下载-超详细

    千次阅读 2013-07-22 13:16:06
    基本原理:利用URLConnection获取要下载文件的长度、头部等相关信息,并设置响应的头部信息。并且通过URLConnection获取输入流,将文件分成指定的块,每一块单独开辟一个线程完成数据的读取、写入。通过输入流读取...
  • Java:多线程:到底什么时候该用多线程

    万次阅读 多人点赞 2018-09-30 16:27:29
    一、高并发 系统接受实现多用户多请求的高并发时,通过多线程来实现。... 这时候可以开线程把花大量时间处理的任务放在线程处理,这样线程在后台处理时,主程序也可以继续执行下去,用户就不需要等待。线...
  • Apache限制下载线程数与带宽详解

    千次阅读 2014-03-11 13:10:48
    找到mod_limitipconn与mod_bw这两个模块,前者是限制下载线程数,后者是限制带宽但是发现,网上90%是转载的文章,有些根本没有实际使用过,经过我花大量的时间,才真正用上了这两个模块。现在一个一个介绍。 首先...
  • mwget 多线程版本wget下载工具

    千次阅读 2017-07-07 20:08:02
    或许有人使用ftp下载,也有人使用多线程的axel以及ProZilla,毫无疑问这两个工具都非常的出色,但是对于习惯使用wget的人来说显得不适应,于是老外便开发了多线程版本的wget工具mwget,m表示multi多线程意思. ...
  • 原文:...说明:mwget和curl/multicurl一样,m就是multi多线程意思。mwget是wget的升级版,支持多线程下载 使用方法: cp mwget /usr/bin chmod +x /usr/bin/mwget
  • 线程10:前台线程和后台线程

    千次阅读 2018-06-08 23:48:28
    线程分为“前台线程”和“后台线程”。1) 应用程序的主线程以及使用Thread构造的线程都默认为前台线程,线程池中的线程是后台线程。(我们默认创建的线程是“前台线程”)。2) 只有所有的前台线程都关闭后,系统...
  • 在多线程下载中,会出现下载的文件(音乐、图片)偏大或偏小。音乐文件可以正常播放,但不是按顺序播放,会发现播放起来里面的内容不是流畅的,可能有几段是重复的;图片也能显示,但不是正常图片,某些部分会重复,...
  • Java实现多线程分片文件下载

    千次阅读 2020-03-08 21:27:43
    所谓分片下载就是要利用多线程的优势,将要下载的文件一块一块的分配到各个线程中去下载,这样就极大的提高了下载速度。 技术难点 并不能说是什么难点,只能说没接触过不知道罢了。 1、如何请求才能拿到数据的特定...
  • 什么是线程安全与非线程安全? 线程安全就是在多线程环境下也不会出现数据不一致,而非线程安全就有可能出现数据不一致的情况。 线程安全由于要确保数据的一致性,所以对资源的读写进行了控制,换句话说增加了...
  • 彻底理解js是单线程

    千次阅读 多人点赞 2020-04-29 13:28:37
    那么问题来了,什么是线程?进程又是什么? 在分析浏览器的渲染过程之前,我们先了解一下什么是进程和线程: (1)什么是进程? 进程是CPU进行资源分配的基本单位 (2)什么是线程线程是CPU调度的最小单位,是...
  • 线程基础

    千次阅读 2021-05-12 16:52:14
    线程
  • 系统接受实现多用户多请求的高并发时,通过多线程来实现。 二、线程后台处理大任务 一个程序是线性执行的。如果程序执行到要花大量时间处理的任务时,那主程序就得等待其执行完才能继续执行下面的。那用户就不得...
  • 线程中的饥饿,其意思是,线程的调度如果只考虑线程优先级的话,那么在线程执行队列中,如果有高优先级的线程插入,该线程就会插入到低优先级线程的前方,这样可能导致低优先级的线程无法执行,最终造成低优先级...
  • IDM下载器是一款优秀的下载软件,它的体积小巧,功能却十分强大,比起同类型的产品,IDM下载器界面更加清爽,占用资源更少以保证运行流畅,可将下载速度提高数倍。 一.界面展示 软件点此下载:IDM 更多热门软件:点...
  • 线程与多线程的区别

    万次阅读 多人点赞 2018-07-02 13:33:12
    什么是线程线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。什么是线程?多线程是指程序中包含多个执行流,即在一个程序中...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 61,635
精华内容 24,654
关键字:

下载线程是什么意思