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