创建线程的三种方法
runnable还需要通过currentthread来获取当前方法,才能使用Thread中的方法
第三种实现方法过程:
1.创建一个类MyCallable实现Callable接口
2.重写call (是有返回值的,表示多线程运行的结果)
3.创建MyCallable的对象 (表示多线程要执行的任务)
4.创建FutureTask的对象 (作用管理多线程运行的结果)
5.创建Thread类的对象,并启动 (表示线程)
MyCallable mc = new MyCallable();创建callable对象
FutureTask<Integer> ft = new FutureTask<>(mc); 创建futuretask管理运行结果
Thread t1 = new Thread(ft);创建线程对象,这个跟Runnable一样需要将接口的实现类作为参数放到Tread的实例方法中
t1.start();开启线程
多线程常用的成员方法
- 优先级默认为5,可以设置1-9之间,代表抢占CPU的概率
- 守护线程表示,当非守护线程关闭之后,守护线程会慢慢关闭
- 礼让线程是该线程执行完之后,可以让出cpu,与别的线程再次竞争
- t.join()表示先让t执行在main线程的前面,这个也可以控制线程的执行顺序
synchronized同步代码块与同步方法
两个注意点:
1、同步代码块在循环里面
2、锁对象要全局唯一
3、可以将该关键字方法上,此方法就是同步方法
- 如果是静态方法,就是这个类的字节码文件对象
- 如果是公开的方法,锁对象为调用此方法的对象this
- stringbuilder中方法都不是同步方法,stringbuffer都是同步方法,所以是线程安全的(单线程可以使用stringbuilder,多线程可以使用stringbuffer)
锁特性
1)死锁:多个锁对象互相引用
2)等待唤醒机制:锁对象.notifyall()方法唤醒 锁对象.wait()
3)阻塞队列:第一种是linkedBlockingQueue,另外一个是ArrayBlockingQueue。后面阻塞队列中,可以调用put和get方法去存或者取数据,两个方法中分别判断了队列中的数据长度是否和数组长度相同以及是否为0,是就会等待。
区别在于:
- 1、底层一个是链表、一个是数组
- 2、一个有界一个无界
- 3、一个有一把锁,一个有两把
4)线程池:把创建线程的任务交给线程池
- 1、定长线程池newfixedthreadpool
- 2、newcachedthreadpool可缓存线程池,没有核心线程数
- 3、newsinglethreadpool单线程,保证程序顺序执行
- 4、延迟和周期执行的线程