目录
通过setName()为线程起名 编辑(2)实现Runnable接口编辑
(1)public static void sleep(long )
一、Java如何实现多线程、
第一种:继承Thread类并重写run方法。
第二种:实现Runnable接口
第三种:实现callable接口
(1)继承Thread类并重写run方法。
1.获取当前线程的名称
第一种:通过父类Thread中的getName()可以获取线程名称。必须为Thread的子类
第二种:通过Thread类中的静态方法currentThread获取当前线程,getName()获取线程名。任意处获取线程名
2.为线程起名
通过setName()为线程起名
(2)实现Runnable接口
能实现接口的就不要继承父类。因为父类只需要单继承。扩展性比较差。
二、Thread类中常用的方法
(1)public static void sleep(long )
(2) yield
当前线程主动放弃时间片,回到就绪状态,竞争下一次时间片
(3)join方法
允许其他线程加入到当前线程中,直到其他线程执行完毕后,当前线程才会执行
三、线程安全的解决办法
四、死锁以及如何避免死锁。
如何避免:
-
尽量不要使用锁的嵌套。
-
不要使用锁,而使用安全类。java.util.concurrent下的类
-
设置锁的超时时间。Lock锁。到达指定时间没有获取锁,则不会再等待该锁。
五、线程通信
等待
-
public final void wait () wait方法调用必须放在同步方法中或者同步方法块中
public 【syn(同步)】void wait (){ 或者【syn(同步)】{ wait(); } }
-
public final void wait (long timeout)
-
必须在对obj加锁的同步代码块中。在一个线程中,调用obj。wait()时,此线程会释放其拥有的所有锁标记,同时此线程阻塞在o的等待队列中。 释放锁,进入等待队列。
通知
- public final void notify()随机唤醒等待队列的一个线程
- public final void notifyAll()唤醒等待队列中的所有线程
等待队列中 该队列的线程必须有人唤醒,唤醒后该线程会进入就绪队列,参与锁的竞争
1.sleep和wait的区别
- wait需要使用notify或notifyAll唤醒,而sleep到时间自动唤醒。
- wait来自于Object类中,sleep来自Thread类中
- wait会是否锁资源,sleep不会释放锁资源。
- wait必须放在同步代码中,而sleep可以放在任意位置。
六、线程的状态
- NEW:新建状态。当new一个线程对象时进入该状态。
- RUNNABLE:运行状态。调用完start并获取cpu时间片进入运行状态
- BLOCKED: 堵塞状态。当没有获取锁资源时
- WAITING: 当执行了wait方法时,该线程进入等待状态。
- TIMED_WAITING:当执行sleep方法时,进入该状态
- TERMINATED: 终止。 当线程执行完毕或出现异常中断。
七、线程池
问题
线程是宝贵的内存资源、单个线程约占1mb空间,过多的分配易造成内存的溢出。
频繁的创建及销毁线程会增加虚拟机回收频率、资源开销,造成程序性能下降。
线程池
线程容器,可设定线程分配的数量上限。
将预先创建的线程对象存入池中,并重用线程池中的线程对象。
避免频繁的创建和销毁。
2 如何创建线程池
(1)线程池的种类:
- 固定长度的线程池
- 单一线程池
- 可变线程池
- 延迟线程池
(2)线程池中参数的意思.
- core: 核心线程数
- max: 最大线程池数
- long: 等待时长
- unit: 等待单位
- BlockQueue:等待队列对象。
3 synchronized和lock的区别
- synchronized自动上锁和解锁,而lock需要手动上锁和解锁。
- synchronized可以给代码块和方法上锁,而lock只能给代码块加锁。
- lock可以知道是否获取锁资源。