编程语言
首页 > 编程语言> > [JavaSE] 第七章 多线程

[JavaSE] 第七章 多线程

作者:互联网

7.1 基本概念

7.2 线程的创建和使用

7.2.1 继承 Thread 类创建多线程

//1.创建一个继承于 Thread 类的子类
class MyThread extends Thread {
    //2.重写 Thread 类的 run()
    @Override
    public void run() {

        for (int i = 0; i < 1000; i++) {
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}
public class ThreadTest {

    public static void main(String[] args) {
        //3.创建 Thread 类的子类的对象
        MyThread t1 = new MyThread();

        //4.通过此对象调用 start():① 启动当前线程;② 调用当前线程的 run()
        t1.start();
        //问题一:我们不能通过直接调用 run() 的方式来启动线程
        //t1.run();

        //问题二:不能让已经 start() 的线程再去执行。会报 IllegalThreadStateException
        //t1.start();
        //我们需要重新创建一个线程的对象
        MyThread t2 = new MyThread();
        t2.start();

        for (int i = 0; i < 1000; i++) {
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + ":" + i + "********main()*********");
            }
        }

    }
}

7.2.2 实现 Runnable 接口创建多线程

//1.创建一个实现了 Runnable 接口的类
class MyThread3 implements Runnable {

    //2.实现类去实现 Runnable 中的抽象方法:run()
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

public class ThreadTest1 {

    public static void main(String[] args) {
        //3.创建实现类的对象
        MyThread3 t1 = new MyThread3();

        //4.将此对象作为参数传递到 Thread 类的构造器中,创建 Thread 类的对象
        Thread tt1 = new Thread(t1);

        //5.通过 Thread 类的对象调用 start()
        tt1.setName("tt1");
        tt1.start();

        //再启动一个线程,遍历 100 以内的偶数
        Thread tt2 = new Thread(t1);
        tt2.setName("tt2");
        tt2.start();
    }
}

7.2.3 两种实现多线程方式对比

7.2.4 Thread 类的有关方法

public class ThreadMethodTest {

    public static void main(String[] args) {

        //MyThread2 t1 = new MyThread2();
        //给线程命名(方式一)
        //t1.setName("线程一");

        //方式二
        MyThread2 t1 = new MyThread2("分线程一");
        t1.setPriority(Thread.MAX_PRIORITY);
        t1.start();
        Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
        //给主线程命名
        Thread.currentThread().setName("主线程");
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + ":" + Thread.currentThread().getPriority() + ":" + i + "********main()*********");
            }

            if (i == 20) {
                try {
                    t1.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        System.out.println(t1.isAlive());
    }
}

class MyThread2 extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {

//                try {
//                    sleep(10);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
                System.out.println(getName() + ":" + getPriority() + ":" + i);
            }
            if (i % 20 == 0) {
                yield();
            }
        }
    }
    public MyThread2(String name) {
        super(name);
    }

    public MyThread2() {
    }
}

7.2.5 线程的调度

7.2.6 线程的优先级

7.2.7 线程的分类

Java 中的线程分为两类:一种是守护线程,一种是用户线程

7.3 线程的生命周期

image-20211230225405625

7.4 线程的同步

7.4.1 线程安全问题

class Window extends Thread {
    private static int ticket = 100;

    @Override
    public void run() {
        while (true) {
            if (ticket > 0) {
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(getName() + ": 卖票,票号为:" + ticket);
                ticket --;
            } else {
                break;
            }
        }
    }
}

public class WindowTest {

    public static void main(String[] args) {

        Window t1 = new Window();
        Window t2 = new Window();
        Window t3 = new Window();

        t1.setName("窗口一");
        t2.setName("窗口二");
        t3.setName("窗口三");

        t1.start();
        t2.start();
        t3.start();
    }
}

7.4.2 同步代码块

* 说明:1.操作共享数据的代码,即为需要被同步的代码。
*      
*      
*          
*      补充:
* 方式二:同步方法
*      
* 说明:关于同步方法的总结
*      1.
*      2.
*        
*
* 5.
*  

7.4.3 同步方法

7.4.4 Lock 锁

7.4.5 死锁问题

public class ThreadTest {

public static void main(String[] args) {

    StringBuffer s1 = new StringBuffer();
    StringBuffer s2 = new StringBuffer();

    new Thread(){
        @Override
        public void run() {
            synchronized (s1) {
                s1.append("a");
                s2.append("1");

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (s2) {
                    s1.append("b");
                    s2.append("2");

                    System.out.println(s1);
                    System.out.println(s2);
                }
            }
        }
    }.start();

    new Thread(new Runnable() {
        @Override
        public void run() {
            synchronized (s2) {
                s1.append("c");
                s2.append("3");

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (s1) {
                    s1.append("d");
                    s2.append("4");

                    System.out.println(s1);
                    System.out.println(s2);
                }
            }
        }
    }).start();
}

}




## 7.5 线程的通信

- `wait()`:一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器
- `notify()`:一旦执行此方法,就会唤醒被 wait 的一个线程。如果有多个线程被 wait,就唤醒优先级高的那个
- `notifyAll()`:一旦执行此方法,就会唤醒所有被 wait 的线程
- `wait()`,`notify()`,`notifyAll()` 三个方法必须使用在同步方法块或同步方法当中
- `wait()`,`notify()`,`notifyAll()` 三个方法的调用者必须是同步代码块或同步方法中的同步监视器。否则,会出现 `IllegalMonitorStateException` 异常
- `wait()`,`notify()`,`notifyAll()` 三个方法是定义在 `java.lang.Object` 类中
- `sleep()` 和 `wait()` 的异同?
- 相同点:一旦执行方法,都可以使得当前的线程进入阻塞状态
- 不同点:
  - 两个方法声明的位置不同:Thread 类中声明 sleep(),Object 类中声明 wait()
  - 调用的要求不同:sleep() 可以在任何需要的场景下调用。wait() 必须使用在同步代码块或同步方法中调用
  - 关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep() 不会释放锁,wait() 会释放锁

~~~java
class Number implements Runnable {

  private int number = 1;

  @Override
  public void run() {
      while (true) {
          synchronized (this) {
              notify();
              if (number < 100) {

                  try {
                      Thread.sleep(10);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }

                  System.out.println(Thread.currentThread().getName() + ":" + number);
                  number ++;

                  try {
                      wait();//调用wait()方法的线程进入堵塞状态
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              } else {
                  break;
              }
          }
      }
  }
}

public class communicationTest {

  public static void main(String[] args) {

      Number number = new Number();

      Thread t1 = new Thread(number);
      Thread t2 = new Thread(number);

      t1.setName("线程1");
      t2.setName("线程2");

      t1.start();
      t2.start();
  }

}

7.6 JDK5.0 新增线程创建方式

7.6.1 实现 Callable 接口创建多线程

//1.创建一个 Callable 的实现类
class NumThread implements Callable {

    //2.实现 call 方法,将此线程需要执行的操作声明在 call() 中
    @Override
    public Object call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            if (i % 2 == 0) {
                System.out.println(i);
                sum += i;
            }
        }
        return sum;
    }
}
public class ThreadNew {

    public static void main(String[] args) {
        //3.创建Callable接口实现类的对象
        NumThread numThread = new NumThread();

        //4.将此Callable接口实现类的对象FutureTask构造器中,创建FutureTask的对象
        FutureTask task = new FutureTask(numThread);

        //5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread类的对象,并调用start()
        Thread t1 = new Thread(task);
        t1.start();

        try {
            //6.get() 返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值
            Object sum = task.get();
            System.out.println("总和为:" + sum);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

7.6.2 使用线程池

class NumberThread implements Runnable {

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

class NumberThread2 implements Runnable {

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            if (i % 2 != 0) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

class NumberThread3 implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        for (int i = 1; i <= 100; i++) {
            if (i % 10 == 0) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
        return null;
    }
}

public class ThreadPool {

    public static void main(String[] args) {

        //1.提供指定线程数量的线程池
        ExecutorService service = Executors.newFixedThreadPool(10);
        ThreadPoolExecutor service2 = (ThreadPoolExecutor) service;
//        service2.setCorePoolSize(15);


        System.out.println(service.getClass());
        //2.执行指定的线程的操作。需要提供实现Runnable接口或Callable接口的实现类的对象
        service.execute(new NumberThread());//适合用于Runnable
        service.execute(new NumberThread2());

        service.submit(new NumberThread3());//适合用于Callable

        //3.关闭连接池
        service.shutdown();
    }
}

标签:Thread,t1,start,线程,第七章,new,JavaSE,多线程,public
来源: https://www.cnblogs.com/Aunean/p/note_07.html