对于线程对象来说,当你调用的是<代码> start() 代码>,线程会被放到等待队列,等待CPU调度,不一定马上执行;无需等待<代码> run() 代码>方法执行完毕,可以直接执行下面的代码;
而调用的是<强> run() 强>的话,就是当做普通的方法调用,程序还是要顺序执行的;
新建线程的几种方式:
实现<强> Runnable 强>接口,里面实现运行()方法;
然后把这个实现了<强> Runnable 强>接口的类就新建为一个<强>线程t=新线程(新(实现运行的接口的类)),>强调用<强> start() >强方法即可开始一个线程了。记住,<强> start() 强>只是开启,然后就会返回,继续执行<强> start() 强>下面的语句了。
我们可以通过不同的线程执行器来实现多线程的执行,有以下几种执行器:
<代码> ExecutorService exec=Executors.newCachedThreadPool(); 代码>
<代码> ExecutorService exec=Executors.newFixedThreadPool(5); 代码>
<代码> ExecutorService exec=Executors.newSingleThreadExecutor(); 代码>
我们可以对比一下这三者的区别:第一个执行会为每一个任务都创建一个线程,
而第二个则是可以一次性指定要分配多少线程,而第三个则是属于单线程,会一个线程一个线程的依次执行;
会使得任务中断一段时间,相当于变相的阻塞了,可以给其他线程制造机会去执行;
但是我们不能通过睡眠()<代码> 代码>来试图控制线程的顺序执行,而是要考虑用同步控制来实现;
通过使用<代码>产量()代码>方法来给线程调度机制一个暗示:你的工作已经完成的差不多了,可以让别的线程使用CPU了,其功能上跟睡眠()<代码> 代码>其实是差不多的。
指在程序运行的时候在后台提供一种通用服务的线程,并且这种线程并不属于程序总共不可或缺的部分,当所有非后台线程结束时,程序终止,由后台线程创建的线程也是后台线程;
在线程调用<代码> start() 代码>之前,调用<代码> setDaemon(真正);代码>
通过继承<强>线程>强的方式来实现,而且<代码> run() 代码>方法是放在构造函数里面的,也就是说,当初始化一个线程的时候,就自动的开启了线程,记得<强> run() >强方法里面一般都是一个<代码>,()代码>循环;
一个线程可以在其他线程之上调用<代码>加入()代码>方法,如果某个线程在另一个线程t <强> 强>上调用<代码> t.join(); 代码>此线程将被挂起,知道目标线程t结束才恢复。
<>强加入()>强方法,你在一个线程中<强>加入()>强了一个线程进的来,你就要等待这个线程结束了,才可以把自己这个线程给结束掉;<强>加入()>强的底层实现是<代码>等()代码>方法;
<强> Synchronzied; 强>可以用在方法上,也可以用到类上面;
先用锁锁=新的ReentrantLock(); 代码>建出一个锁对象出来,然后在方法里面,先调用<代码> lock.lock(); 代码>然后尝试语句里面是方法体,最后记得要在最后<强> 强>里面加上<强> lock.unlock(); 强>这样就就相当于解锁了。
可以看到<强> 强>同步和锁<强> 强>相比起来,锁似乎要加上一些<强> try/catch >强语句才可以,但是,这也是好处之一,比起同步,可以多出来处理的过程,让用户出现错误的可能性降低;
使用原子类也可以实现资源共享的问题,但是原子类一般很少在常规编程中用到,用于性能调优,然后<强> AtomicInteger, AtomicLong 强>等原子类,使用这些的时候,不需要用到<强> >强,同步和锁但是原子类很少用的到,所以我们还是用同步和锁。
新建;就绪;阻塞;死亡;
1,通过调用睡眠()<代码> 代码>使任务进入休眠状态,
2,通过调用<代码>等()代码>使线程挂起,知道线程得到<代码>通知()代码>或<代码> notifyAll() 代码>消息,
3,任务再等待某个输入/输出完成;
4,任务视图在某个对象上调用其同步控制方法,但是对象锁不可用,因为另一个任务已经获取了这个锁;
这是一个大学问呀,一般的话,我们中断都是用<代码>打断了(),代码>但是,我们现在说了,用<强> Executo 强> r执行器可以更好地执行了,所以我们如如何在执行器中中断线程呢?这也很好办,用<强>执行人的shutdownNow() >强劲,但是,这又是一个问题了,这只是用来中断所有的线程的,但是我们是想要中断某一个线层那该怎么办呢?这就用到了返回式了,通过