Java多线程

进程 VS 线程
并发 VS 并行

实现线程两种方法:
1.extends Thread,重写run方法(class Thread implements Runnable)
2.implements Runnable接口,重写run方法

启动线程用cat.start() 为什么不是 cat.run()
原因:
cat.run是一个普通的方法,没有真正启动一个线程,就会把run方法执行完毕,才向下执行
真正实现多线程的是private native void start0();

源码分析:
start() -> start0(),线程并不一定立马执行,只是将线程变为可运行状态
private native void start0();//本地方法,JVM调用,底层是c/c++实现

用户线程 VS 守护线程
守护线程当用户线程都运行结束后自动结束,如垃圾回收
thread.setDaemon(true);//设置为守护线程

线程的7种状态:NEW RUNNABLE BLOCKED WAITING TIMED_WAITING TERMINATED

在这里插入图片描述

//线程的状态
public class States_ {
    public static void main(String[] args) throws InterruptedException {
        ThreadState threadState = new ThreadState();
        System.out.println("线程的状态:" + threadState.getState());
        threadState.start();
        while (Thread.State.TERMINATED != threadState.getState()) {
            System.out.println("线程的状态:" + threadState.getState());
            Thread.sleep(500);
        }
        System.out.println("线程的状态:" + threadState.getState());
    }
}

class ThreadState extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                System.out.println("线程执行~");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
线程同步:synchronized
可在用在方法上(同步方法)、代码块(同步代码块),要求多个线程的锁对象是同一个
private synchronized void sell() {
} //同步方法
synchronized (对象) {} //同步代码块
同步方法(非静态)的锁对象默认为 this
同步方法(静态)的锁对象默认为 当前类.class

//下面代码存在问题,不能完成互斥同步,原因:同步方法(非静态)的锁不是同一个对象
public class Syncronized_ {
    public static void main(String[] args) {
        
        Cat cat = new Cat();
        cat.start();

        Cat cat1 = new Cat();
        cat1.start();
    }
}

class Cat extends Thread {
    static int ticketNum = 10;
    static boolean loop = true;

    @Override
    public void run() {
        while (loop) {
            sell();
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private synchronized void sell() {
        if (ticketNum > 0) System.out.println(Thread.currentThread().getName() + "卖票:" + ticketNum--);
        else loop = false;
    }
}

修改如下:
方式一:同步方法(静态)的锁为当前类本身,是同一对象
private synchronized static void sell() {
   if (ticketNum > 0) System.out.println(Thread.currentThread().getName() + "卖票:" + ticketNum--);
   else loop = false;
}

方式二:代码块上锁,指定锁对象(只要是同一对象即可)
private void sell() {
    synchronized (Syncronized_.class) {
        if (ticketNum > 0) System.out.println(Thread.currentThread().getName() + "卖票:" + ticketNum--);
        else loop = false;
    }
}

方式三:
public class Syncronized_ {
    public static void main(String[] args) {

        Cat cat = new Cat();
        new Thread(cat).start();
        new Thread(cat).start();
    }
}

class Cat implements Runnable {
    static int ticketNum = 10;
    static boolean loop = true;

    @Override
    public void run() {
        while (loop) {
            sell();
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private synchronized void sell() {
        if (ticketNum > 0) System.out.println(Thread.currentThread().getName() + "卖票:" + ticketNum--);
        else loop = false;
    }
	/*private void sell() {
	    synchronized (this) {
	        if (ticketNum > 0) System.out.println(Thread.currentThread().getName() + "卖票:" + ticketNum--);
	        else loop = false;
	    }
	}*/
}
//线程的两种实现方法
public class Test {

    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.start();//开启子线程

        Dog dog = new Dog();
        Thread thread = new Thread(dog);
        thread.start();//开启子线程

        System.out.println("main主线程启动子线程,main主线程不会阻塞,会继续执行,主线程结束不影响子线程,主线程名:" + Thread.currentThread().getName());
    }
}

class Cat extends Thread {
    @Override
    public void run() {
        while (true) {
            System.out.println("喵喵喵~ " + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Dog implements Runnable {
    @Override
    public void run() {
        while (true) {
            System.out.println("汪汪汪~ " + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
//线程的常用方法
public class Test {

    public static void main(String[] args) throws InterruptedException {
        Cat cat = new Cat();
        cat.setName("cat");//设置线程名称
        cat.setPriority(1);//设置优先级1~10
        cat.start();//开启线程
        System.out.println("main主线程启动子线程,main主线程不会阻塞,会继续执行,主线程结束不影响子线程,主线程名:" + Thread.currentThread().getName());
        Thread.sleep(2 * 1000);
        cat.interrupt();//中断线程
        cat.join();
        System.out.println("join相当于插队到main线程中来,cat线程执行完毕后才执行主线程");
    }
}

class Cat extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("喵喵喵~ " + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("线程被中断~");
            }
        }
    }
}
释放锁:
1.同步方法、同步代码块正常执行结束,或遇到returnbreak
2.同步方法、同步代码块异常结束,出现ErrorException
3.调用wait()方法,当前线程暂停执行并释放锁

不释放锁:
1.调用sleep()yield()方法,当前线程暂停执行并不释放锁
2.线程执行同步代码块时,其他线程调用该线程的suspend()方法将线程挂起,该线程不释放锁。
提示:避免使用suspend()resume()控制线程,方法不再推荐使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值