一、创建线程

1、继承thread类,重新写run方法

  1. public class Test_CreateThread extends Thread {
  2. @Override
  3. public void run() {
  4. //重写run方法 run方法线程体
  5. for (int i = 0; i < 500; i++) {
  6. System.out.println("我在看视频->"+i);
  7. }
  8. }
  9. public static void main(String[] args) {
  10. Test_CreateThread test_createThread=new Test_CreateThread();
  11. //test_createThread.start();
  12. test_createThread.run();
  13. //main主线程体
  14. for (int i = 0; i < 500; i++) {
  15. System.out.println("我在学习多线程->"+i);
  16. }
  17. }
  18. }

2、实现Runnable接口,重写run方法 使用Thread代理

  1. public class Test_CreateThread2 implements Runnable {
  2. @Override
  3. public void run() {
  4. //run方法线程体
  5. for (int i = 0; i < 5; i++) {
  6. System.out.println("我在看视频->" + i);
  7. }
  8. }
  9. public static void main(String[] args) {
  10. Test_CreateThread2 test_createThread2 = new Test_CreateThread2();
  11. // Thread thread=new Thread(test_createThread2);
  12. // thread.start();
  13. new Thread(test_createThread2).start();
  14. for (int i = 0; i < 5; i++) {
  15. System.out.println("我在学习->"+i);
  16. }
  17. }
  18. }

注意:

  • 启动线程的方法不同,调用run()方法时,如果子线程在主线程体之前启动,则会先运行子线程,然后才会执行主线程体语句。

  • 调用start()方法时线程不一定立即执行,由cpu安排调度,就会出现交替执行的情况。如下图

二、Lambda表达式 推导

1、外部类

  1. public class Test_Lambda {
  2. //调用
  3. public static void main(String[] args) {
  4. IRead iRead=new Read();
  5. iRead.read();
  6. }
  7. }
  8. //1、定义一个函数式接口
  9. interface IRead{
  10. void read();
  11. }
  12. //2、实现类 外部类
  13. class Read implements IRead{
  14. @Override
  15. public void read() {
  16. System.out.println("I read book1!");
  17. }
  18. }

外部类修饰符:只能用public、abstract、final修饰

2、静态内部类

  1. public class Test_Lambda {
  2. //2、实现类 内部类
  3. static class Read implements IRead {
  4. @Override
  5. public void read() {
  6. System.out.println("i read book2");
  7. }
  8. }
  9. public static void main(String[] args) {
  10. IRead iRead = new Read();
  11. iRead.read();
  12. }
  13. }
  14. //1、函数式接口
  15. interface IRead {
  16. void read();
  17. }

静态内部类必须加static修饰

内部类修饰符:private、protected、public、final、static、abstract

3、局部内部类

  1. public class Test_Lambda {
  2. public static void main(String[] args) {
  3. //2、实现类 局部内部类
  4. class Read implements IRead{
  5. @Override
  6. public void read() {
  7. System.out.println("i read book3!");
  8. }
  9. }
  10. IRead iRead = new Read();
  11. iRead.read();
  12. }
  13. }
  14. //1、函数式接口
  15. interface IRead {
  16. void read();
  17. }

4、匿名内部类

  1. public class Test_Lambda {
  2. public static void main(String[] args) {
  3. //2、实现类 匿名内部类
  4. new IRead() {
  5. @Override
  6. public void read() {
  7. System.out.println("i read book4!");
  8. }
  9. }.read();
  10. }
  11. }
  12. //1、函数式接口
  13. interface IRead {
  14. void read();
  15. }

5、lambda表达式

  1. public class Test_Lambda {
  2. public static void main(String[] args) {
  3. //2、lambda表达式
  4. IRead read = () -> {
  5. System.out.println("i read book5!");
  6. };
  7. read.read();
  8. }
  9. }
  10. //1、函数式接口
  11. interface IRead {
  12. void read();
  13. }
  • lambda表达式主体只有一句时,{}可以省略
    1. IRead read = () -> System.out.println("i read book5!");
  • 参数类型可以省略 有多个参数时,要省略参数类型就必须全部省略
    1. //IRead read = (int a) -> System.out.println("i read book5!->"+a);
    2. IRead read =(a) -> System.out.println("i read book5!->"+a);
  • 只有一个参数时,()可以省略
    1. IRead read =a-> System.out.println("i read book5!->"+a);

三、线程优先级

  • 线程的优先级值为从1-10的整数,越大则优先级越大。若超出1-10这个范围,就会抛出异常
  • 优先级只能表示线程先执行的可能性越大,但也会出现低优先级先执行的情况。得看cpu调度的心情
  • main主线程的优先级固定不变,为5
  1. public class Test_Priority {
  2. public static void main(String[] args) {
  3. //打印主线程的优先级
  4. System.out.println(Thread.currentThread().getName()+"-> "+Thread.currentThread().getPriority());
  5. TestPriority tp=new TestPriority();
  6. Thread t1=new Thread(tp);
  7. Thread t2=new Thread(tp);
  8. Thread t3=new Thread(tp);
  9. Thread t4=new Thread(tp);
  10. Thread t5=new Thread(tp);
  11. //设置优先级 并启动
  12. t1.start();
  13. t2.setPriority(1);
  14. t2.start();
  15. t3.setPriority(5);
  16. t3.start();
  17. t4.setPriority(10);
  18. t4.start();
  19. t5.setPriority(8);
  20. t5.start();
  21. }
  22. }
  23. class TestPriority implements Runnable{
  24. @Override
  25. public void run() {
  26. System.out.println(Thread.currentThread().getName()+"-> "+Thread.currentThread().getPriority());
  27. }
  28. }

四、线程的同步 synchronized

1、synchronized方法

  • synchronized方法控制对 对象 的访问,每个对象都有一把锁。
  • 添加了synchronized方法后,每个线程调用对象时都需要获得对象的锁,获得之后才能执行,且一直独占对象的锁,直到方法执行完后才会释放,后续线程才能获得这个锁。
  • 方法声明为synchronized会影响效率
  1. public class Test_synchronized {
  2. public static void main(String[] args) {
  3. buyTickets buyTickets=new buyTickets();
  4. new Thread(buyTickets,"小帆").start();
  5. new Thread(buyTickets,"小卿").start();
  6. new Thread(buyTickets,"小陈").start();
  7. }
  8. }
  9. class buyTickets implements Runnable {
  10. private int ticketNum = 10; //票的总数
  11. boolean flag = true; //线程停止标志
  12. @Override
  13. public void run() {
  14. while (flag){
  15. try {
  16. buy();
  17. } catch (InterruptedException e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }
  22. //添加synchronized 同步方法 锁的是buyTickets对象
  23. private synchronized void buy() throws InterruptedException {
  24. if(ticketNum<=0){
  25. flag=false; //票总数为0时,线程结束
  26. return;
  27. }
  28. Thread.sleep(100); //模拟延时,放大问题发生性
  29. System.out.println(Thread.currentThread().getName()+"买到了第"+ticketNum-- +"张票");
  30. }
  31. }

如果不添加synchronized方法锁,就会出现买到负数的票和多人买到同一张票的情况。如下图:

添加synchronized方法后的运行结果如下:

2、synchronized代码块