About the way to create multiple threads

The way to create multithreading is to inherit the Thread class

The way to inherit the Thread class:

    1. Create a subclass that inherits from the Thread class
    1. Override run() of the Thread class --> declare the operation performed by this thread in run()
    1. Create an object of a subclass of the Thread class
    1. Call start() through this object: ①Start the current thread ②Call the run() of the current thread

Code example:

public class ThreadTest {
    
    

    public static void main(String[] args) {
    
    
        //3. 创建Thread类的子类的对象
        MyThread t1 = new MyThread();
        //4.通过此对象调用start():①启动当前线程 ② 调用当前线程的run()
        t1.start();

        //问题一:我们不能通过直接调用run()的方式启动线程。
//        t1.run();
        //问题二:再启动一个线程,遍历100以内的偶数。不可以还让已经start()的线程去执行。会报IllegalThreadStateException
//        t1.start();
        //我们需要重新创建一个线程的对象
        MyThread t2 = new MyThread();
        t2.start();

        //如下操作仍然是在main线程中执行的。
        for (int i = 0; i < 100; i++) {
    
    
            if (i % 2 == 0) {
    
    
                System.out.println(Thread.currentThread().getName() + ";" + i + "***********main()************");
            }
        }
    }
}

//1. 创建一个继承于Thread类的子类
class MyThread extends Thread {
    
    
    //2.重写Thread类的run()
    @Override
    public void run() {
    
    
        //遍历100以内的所有的偶数
        for (int i = 0; i < 100; i++) {
    
    
            if (i % 2 == 0) {
    
    
                System.out.println(Thread.currentThread().getName() + ";" + i);
            }
        }
    }
}

A small screenshot of the output result:
Insert picture description here

注意点:
如果自己手动调用run()方法,那么就只是普通方法,没有启动多线程模式。
run()方法由JVM调用,什么时候调用,执行的过程控制都有操作系统的CPU
调度决定。
想要启动多线程,必须调用start方法。
一个线程对象只能调用一次start()方法启动,如果重复调用了,则将抛出以上的异常“IllegalThreadStateException”。

Example: Window ticket sales
have thread safety issues, to be resolved

public class WindowTest {
    
    

    public static void main(String[] args) {
    
    
        Window t1 = new Window();
        Window t2 = new Window();
        Window t3 = new Window();

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

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

class  Window extends  Thread{
    
    
    //声明总票数为100
    private  static int ticket = 100;
    @Override
    public void run() {
    
    
        while (true){
    
    
            if(ticket>0){
    
    
                System.out.println(getName() + ":卖票,票号为:" + ticket);
                ticket--;
            }else {
    
    
                break;
            }
        }
    }
}

Insert picture description here

The second way of creating multithreading is to implement the Runnable interface

The way to implement Runnable interface:

    1. Create a class that implements the Runnable interface
    1. Implementation class to implement the abstract method in Runnable: run()
    1. Create an object of the implementation class
    1. Pass this object as a parameter to the constructor of the Thread class to create an object of the Thread class
    1. Call start() through an object of the Thread class
public class ThreadTest {
    
    
    public static void main(String[] args) {
    
    
        //3. 创建实现类的对象
        MThread mThread = new MThread();

        //4. 将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
        Thread t1 = new Thread(mThread);
        t1.setName("线程1");
        //5. 通过Thread类的对象调用start():① 启动线程 ②调用当前线程的run()-->调用了Runnable类型的target的run()
        t1.start();

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

//1. 创建一个实现了Runnable接口的类
class MThread 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);
            }

        }
    }
}

Solve the thread safety problem of multi-window ticket selling:

public class WindowTest1 {
    
    
    public static void main(String[] args) {
    
    
        Window1 w = new Window1();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

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

class Window1 implements Runnable {
    
    

    private int ticket = 100;

    @Override
    public void run() {
    
    
        while (true) {
    
    
            if (ticket > 0) {
    
    
                System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
                ticket--;
            } else {
    
    
                break;
            }
        }

    }
}

Comparison of Method 1 and Method 2

* 开发中:优先选择:实现Runnable接口的方式
* 原因:1. 实现的方式没类的单继承性的局限性
*      2. 实现的方式更适合来处理多个线程共享数据的情况。

* 相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中。
          目前两种方式,要想启动线程,都是调用的Thread类中的start()

The third way to create multithreading is to implement the Callable interface — new in JDK 5.0

New method 1: Implement Callable interface. — New in JDK 5.0.
Compared with Runnable, Callable has more powerful functions.
Compared with run() method, it can have return value.
Method can throw exception.
Support generic return value. You
need to use FutureTask class, such as getting the return result.

//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 futureTask = new FutureTask(numThread);
        //5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
        new Thread(futureTask).start();

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

}

Description:

  • How to understand that the way of implementing the Callable interface to create multiple threads is more powerful than the way of implementing the Runnable interface to create multiple threads?
    1. call() can return a value.
    1. call() can throw exceptions, be caught by outside operations, and get exception information
    1. Callable supports generics

The fourth way to create multithreading is to use thread pool-new in JDK 5.0

New method 2: Use thread pool to develop frequently used

class NumberThread implements Runnable{
    
    

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

class NumberThread1 implements Runnable{
    
    

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

public class ThreadPool {
    
    

    public static void main(String[] args) {
    
    
        //1. 提供指定线程数量的线程池
        ExecutorService service = Executors.newFixedThreadPool(10);
        ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
        //设置线程池的属性
//        System.out.println(service.getClass());
//        service1.setCorePoolSize(10);
//        service1.setKeepAliveTime();


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

//        service.submit(Callable callable);//适合使用于Callable
        //3.关闭连接池
        service.shutdown();
    }

}

Description:

  • benefit:
  • 1. Improve response speed (reduce the time to create new threads)
  • 2. Reduce resource consumption (reuse threads in the thread pool, no need to create each time)
  • 3. Easy thread management
  •  corePoolSize:核心池的大小
    
  •  maximumPoolSize:最大线程数
    
  •  keepAliveTime:线程没任务时最多保持多长时间后会终止
    

Guess you like

Origin blog.csdn.net/sss153/article/details/107821583