概念
注: main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集(gc )线程。
线程的创建
第一种:继承Thread类,重写run方法(其底层也是实现了Ruunable接口)
第二种:实现Runnable接口,重写run方法(启动线程时要把对象丢进Thread对象中)
两种方式的总结:
实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类
第三种:实现Callable接口(了解)
线程属性
①线程ID,标识线程
②线程名字 ③线程优先级(1-10),优先级越高越优先执行,但并不成正比关系
④线程状态,NEW RUNNALBE BLOCKED WAITING TERMINATED
⑤线程类别,ture标识守护线程(后台记录操作日志,监控内存,垃圾回收),false标识用户线程。虚拟机必须保证用户线程的执行完毕,不用等待守护线程执行
线程状态
线程休眠sleep():
①参数为阻塞线程的毫秒数
②阻塞时间到了之后线程进入就绪状态
③每个对象都有一把锁,sleep不会释放锁
等待线程停止join():
①相当于插队,在主线程中是子线程join(),即主线程等待子线程执行完毕再执行
线程礼让yield():
①礼让的意思是停止cpu对该进程的执行,即从运行状态变成就绪状态
②礼让不一定成功,得看cpu的调度
线程停止:
①使其自动运行完然后停止
②可以设置一个标志位flag来停止线程
③不要使用stop()和destory()等过时或者JDK不建议的方法去停止线程
线程同步(并发)
package Algorithm.SYN;
public class UnsafeThread {
public static void main(String[] args) {
Buytciket buytciket = new Buytciket();
new Thread(buytciket,"1号").start();
new Thread(buytciket,"2号").start();
new Thread(buytciket,"3号").start();
}
}
class Buytciket implements Runnable{
//定义总数量
private int TicketNum = 10;
boolean flag = true;
@Override
public void run() {
//买票
while (flag){
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void buy() throws InterruptedException {
//判断是否有票
if(TicketNum <= 0){
flag = false;
return;
}
//模拟延时
Thread.sleep(100);
//买票
System.out.println(Thread.currentThread().getName()+"买到了第"+TicketNum--+"票");
}
}
可见出现了线程的并发问题。
锁机制(synchronized):
synchronized锁又可以分为synchronized方法和synchronized块:其默认锁的是this,即对象本身。synchronized块锁的是变化的量(对象)。
//synchronized同步方法
private synchronized void buy() throws InterruptedException {
//判断是否有票
if(TicketNum <= 0){
flag = false;
return;
}
//买票
System.out.println(Thread.currentThread().getName()+"买到了第"+TicketNum--+"票");
}
拓展:JUC包下的安全集合CopyOnWriteArrayList,可以实现线程集合安全
死锁
private void mu() throws InterruptedException {
if(choice == 0){
//获得口红
synchronized (lipstick){
System.out.println(this.name+"获得口红");
Thread.sleep(1000);
synchronized (m){
System.out.println(this.name+"获得镜子");
}
}
}
else{
//获得口红
synchronized (m){
System.out.println(this.name+"获得镜子");
Thread.sleep(2000);
synchronized (lipstick){
System.out.println(this.name+"获得口红");
}
}
}
发生死锁!!进程全部阻塞
private void mu() throws InterruptedException {
if(choice == 0){
//获得口红
synchronized (lipstick){
System.out.println(this.name+"获得口红");
Thread.sleep(1000);
}
synchronized (m){
System.out.println(this.name+"获得镜子");
}
}
else{
//获得口红
synchronized (m){
System.out.println(this.name+"获得镜子");
Thread.sleep(2000);
}
synchronized (lipstick){
System.out.println(this.name+"获得口红");
}
}
产生死锁的条件:
Lock锁(显式)
两种锁的对比:
线程池
public class pool {
public static void main(String[] args) {
//创建线程池
ExecutorService service = Executors.newFixedThreadPool(10);//线程池大小
//执行
service.execute(new my());
service.execute(new my());
service.execute(new my());
service.execute(new my());
//关闭连接
service.shutdown();
}
}
class my implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}