Java多线程创建及典型实例(多线程买票)

请添加图片描述

多线程

1. Thread

第一种方式创建多线程

package JavaPackage_13;

public class JavaCode {
    public static void main(String[] args) {
        new MyThread().start();
        System.out.println(Thread.currentThread().getName()); // main
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(i + Thread.currentThread().getName());
        }
    }
}
package JavaPackage_13;

public class JavaCode {
    public static void main(String[] args) throws InterruptedException {
        new MyThread().start();
        Thread.sleep(10);
        System.out.println(Thread.currentThread().getName()); // main
        Thread.currentThread().setName("主线程");
        System.out.println(Thread.currentThread().getName());
        System.out.println(Thread.currentThread().isAlive());
        Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
        System.out.println(Thread.currentThread().getPriority()); // 5
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(i + Thread.currentThread().getName() + " " + getPriority());
        }
    }
}

2. Runnable

第二种方式创建多线程

package JavaPackage_13;

public class JavaCode {
    public static void main(String[] args) {
        Window window = new Window();
        Thread thread1 = new Thread(window);
        Thread thread2 = new Thread(window);
        Thread thread3 = new Thread(window);
        thread1.setName("窗口1");
        thread2.setName("窗口2");
        thread3.setName("窗口3");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

class Window implements Runnable {

    private int ticket = 100;

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

3. 线程通信

线程通信:线程1、2交替打印数字1-100

package JavaPackage_13;

public class JavaCode {
    public static void main(String[] args) {
        Number number = new Number();
        Thread thread1 = new Thread(number);
        Thread thread2 = new Thread(number);
        thread1.start();
        thread2.start();
    }
}

class Number implements Runnable {
    private int num = 1;
    @Override
    public void run() {
        while (true) {
            synchronized (this) {
                notify();
                if (num < 100) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":" + num++);
                }
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

4. Callable

第三种方式创建多线程

package JavaPackage_13;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class JavaCode {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        FutureTask<Integer> futureTask = new FutureTask<Integer>(myThread);
        Thread thread = new Thread(futureTask);
        thread.start();
        try {
            // 获取返回值
            Integer sum = futureTask.get();
            System.out.println(sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

class MyThread implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i <= 100; i++) {
            sum += i;
        }
        return sum;
    }
}

5. 线程池

第四种方式创建多线程

线程池创建多线程

	package JavaPackage_13;

import java.util.concurrent.*;

public class JavaCode {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10); // 接口
        ThreadPoolExecutor service = (ThreadPoolExecutor) executorService;
        //设置属性
        service.setCorePoolSize(15);
        try {
            System.out.println(executorService.submit(new MyThread()).get());// 适用于Callable
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        executorService.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println(i + Thread.currentThread().getName());
                }
            }
        }); // 适用于Runnable
        //关闭连接池
        executorService.shutdown();
    }
}

class MyThread implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i <= 100; i++) {
            sum += i;
        }
        return sum;
    }
}

多线程卖票实例

1. 继承Thread类(存在线程安全问题)

package JavaPackage_13;

public class JavaCode {
    public static void main(String[] args) {
        Window window1 = new Window();
        Window window2 = new Window();
        Window window3 = new Window();
        window1.setName("窗口1");
        window2.setName("窗口2");
        window3.setName("窗口3");
        window1.start();
        window2.start();
        window3.start();
    }
}

class Window extends Thread {

    private static int ticket = 100;

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

2. 实现Runnable接口(存在线程安全问题)

package JavaPackage_13;

public class JavaCode {
    public static void main(String[] args) {
        Window window = new Window();
        Thread thread1 = new Thread(window);
        Thread thread2 = new Thread(window);
        Thread thread3 = new Thread(window);
        thread1.setName("窗口1");
        thread2.setName("窗口2");
        thread3.setName("窗口3");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

class Window implements Runnable {

    private int ticket = 100;

    @Override
    public void run() {
        while (true) {
            if (ticket > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":票号:" + ticket--);
            } else {
                break;
            }
        }
    }
}
窗口1:票号:100
窗口3:票号:100
窗口2:票号:100
窗口2:票号:99
窗口3:票号:97
窗口1:票号:98
窗口2:票号:96
窗口3:票号:95
窗口1:票号:94
窗口2:票号:93
窗口3:票号:92
窗口1:票号:91
窗口3:票号:90
窗口2:票号:90
窗口1:票号:89
窗口3:票号:88
窗口2:票号:87
窗口1:票号:86
窗口3:票号:85
窗口2:票号:84
窗口1:票号:83
窗口3:票号:82
窗口2:票号:81
窗口1:票号:80
窗口3:票号:79
窗口2:票号:78
窗口1:票号:77
窗口3:票号:76
窗口2:票号:75
窗口1:票号:74
窗口3:票号:73
窗口2:票号:72
窗口1:票号:71
窗口3:票号:70
窗口2:票号:69
窗口1:票号:68
窗口3:票号:67
窗口2:票号:66
窗口1:票号:65
窗口3:票号:64
窗口2:票号:63
窗口1:票号:62
窗口3:票号:61
窗口2:票号:60
窗口1:票号:59
窗口3:票号:58
窗口2:票号:57
窗口1:票号:56
窗口3:票号:55
窗口2:票号:54
窗口1:票号:53
窗口3:票号:52
窗口2:票号:51
窗口1:票号:50
窗口3:票号:49
窗口2:票号:48
窗口1:票号:47
窗口3:票号:46
窗口2:票号:45
窗口1:票号:44
窗口3:票号:43
窗口2:票号:42
窗口1:票号:41
窗口3:票号:40
窗口2:票号:39
窗口1:票号:38
窗口3:票号:37
窗口2:票号:36
窗口1:票号:35
窗口3:票号:34
窗口2:票号:33
窗口1:票号:32
窗口3:票号:31
窗口2:票号:30
窗口1:票号:29
窗口3:票号:28
窗口2:票号:27
窗口1:票号:26
窗口3:票号:25
窗口2:票号:24
窗口1:票号:23
窗口3:票号:22
窗口2:票号:21
窗口1:票号:20
窗口3:票号:19
窗口2:票号:18
窗口1:票号:17
窗口3:票号:16
窗口2:票号:15
窗口1:票号:14
窗口3:票号:13
窗口2:票号:12
窗口1:票号:11
窗口3:票号:10
窗口2:票号:9
窗口1:票号:8
窗口3:票号:7
窗口2:票号:6
窗口1:票号:5
窗口3:票号:4
窗口2:票号:3
窗口1:票号:2
窗口3:票号:1
窗口2:票号:0
窗口1:票号:-1

Process finished with exit code 0

3. 对线程安全问题的解决

通过同步机制解决线程安全问题

3.1 Runnable(同步代码块)

可以考虑使用this充当同步监视器

synchronized(同步监视器[]){ // 任何一个类的对象都可以充当锁 多个线程必须要共用同一把锁
    被同步的代码
}

操作同步代码时,只能有一个线程参与,其他线程等待,效率低。

package JavaPackage_13;

public class JavaCode {
    public static void main(String[] args) {
        Window window = new Window();
        Thread thread1 = new Thread(window);
        Thread thread2 = new Thread(window);
        Thread thread3 = new Thread(window);
        thread1.setName("窗口1");
        thread2.setName("窗口2");
        thread3.setName("窗口3");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

class Window implements Runnable {

    private int ticket = 100;

    @Override
    public void run() {
        while (true) {
            synchronized (this) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":票号:" + ticket--);
                } else {
                    break;
                }
            }
        }
    }
}
窗口1:票号:100
窗口1:票号:99
窗口1:票号:98
窗口1:票号:97
窗口1:票号:96
窗口1:票号:95
窗口1:票号:94
窗口1:票号:93
窗口1:票号:92
窗口1:票号:91
窗口1:票号:90
窗口1:票号:89
窗口1:票号:88
窗口1:票号:87
窗口1:票号:86
窗口1:票号:85
窗口1:票号:84
窗口1:票号:83
窗口1:票号:82
窗口1:票号:81
窗口1:票号:80
窗口1:票号:79
窗口1:票号:78
窗口1:票号:77
窗口1:票号:76
窗口1:票号:75
窗口1:票号:74
窗口1:票号:73
窗口1:票号:72
窗口1:票号:71
窗口1:票号:70
窗口1:票号:69
窗口1:票号:68
窗口1:票号:67
窗口1:票号:66
窗口1:票号:65
窗口1:票号:64
窗口1:票号:63
窗口1:票号:62
窗口1:票号:61
窗口1:票号:60
窗口1:票号:59
窗口1:票号:58
窗口1:票号:57
窗口1:票号:56
窗口1:票号:55
窗口1:票号:54
窗口1:票号:53
窗口1:票号:52
窗口1:票号:51
窗口1:票号:50
窗口1:票号:49
窗口1:票号:48
窗口1:票号:47
窗口1:票号:46
窗口1:票号:45
窗口1:票号:44
窗口1:票号:43
窗口1:票号:42
窗口1:票号:41
窗口1:票号:40
窗口1:票号:39
窗口1:票号:38
窗口1:票号:37
窗口1:票号:36
窗口1:票号:35
窗口1:票号:34
窗口1:票号:33
窗口1:票号:32
窗口1:票号:31
窗口1:票号:30
窗口1:票号:29
窗口1:票号:28
窗口1:票号:27
窗口1:票号:26
窗口1:票号:25
窗口1:票号:24
窗口1:票号:23
窗口1:票号:22
窗口1:票号:21
窗口1:票号:20
窗口1:票号:19
窗口1:票号:18
窗口1:票号:17
窗口1:票号:16
窗口1:票号:15
窗口1:票号:14
窗口1:票号:13
窗口1:票号:12
窗口1:票号:11
窗口1:票号:10
窗口1:票号:9
窗口1:票号:8
窗口1:票号:7
窗口1:票号:6
窗口1:票号:5
窗口1:票号:4
窗口1:票号:3
窗口1:票号:2
窗口1:票号:1

Process finished with exit code 0

3.2 Thread(同步代码块)

可以考虑使用当前类xxx.class充当同步监视器

package JavaPackage_13;

public class JavaCode {
    public static void main(String[] args) {
        Window window1 = new Window();
        Window window2 = new Window();
        Window window3 = new Window();
        window1.setName("窗口1");
        window2.setName("窗口2");
        window3.setName("窗口3");
        window1.start();
        window2.start();
        window3.start();
    }
}

class Window extends Thread {

    private static int ticket = 100;

    @Override
    public void run() {
        while (true) {
            synchronized (Window.class) { // 不能使用this
                if (ticket > 0) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":票号:" + ticket--);
                } else {
                    break;
                }
            }
        }
    }
}
窗口1:票号:100
窗口1:票号:99
窗口1:票号:98
窗口1:票号:97
窗口1:票号:96
窗口1:票号:95
窗口1:票号:94
窗口1:票号:93
窗口1:票号:92
窗口1:票号:91
窗口1:票号:90
窗口1:票号:89
窗口1:票号:88
窗口1:票号:87
窗口1:票号:86
窗口1:票号:85
窗口1:票号:84
窗口1:票号:83
窗口1:票号:82
窗口1:票号:81
窗口1:票号:80
窗口1:票号:79
窗口1:票号:78
窗口1:票号:77
窗口1:票号:76
窗口1:票号:75
窗口1:票号:74
窗口1:票号:73
窗口1:票号:72
窗口1:票号:71
窗口1:票号:70
窗口1:票号:69
窗口1:票号:68
窗口1:票号:67
窗口1:票号:66
窗口1:票号:65
窗口1:票号:64
窗口1:票号:63
窗口1:票号:62
窗口1:票号:61
窗口1:票号:60
窗口1:票号:59
窗口1:票号:58
窗口1:票号:57
窗口1:票号:56
窗口1:票号:55
窗口1:票号:54
窗口1:票号:53
窗口1:票号:52
窗口1:票号:51
窗口1:票号:50
窗口1:票号:49
窗口1:票号:48
窗口1:票号:47
窗口1:票号:46
窗口1:票号:45
窗口1:票号:44
窗口1:票号:43
窗口1:票号:42
窗口1:票号:41
窗口1:票号:40
窗口1:票号:39
窗口1:票号:38
窗口1:票号:37
窗口1:票号:36
窗口1:票号:35
窗口1:票号:34
窗口1:票号:33
窗口1:票号:32
窗口1:票号:31
窗口1:票号:30
窗口1:票号:29
窗口1:票号:28
窗口1:票号:27
窗口1:票号:26
窗口1:票号:25
窗口1:票号:24
窗口1:票号:23
窗口1:票号:22
窗口1:票号:21
窗口1:票号:20
窗口1:票号:19
窗口3:票号:18
窗口3:票号:17
窗口3:票号:16
窗口3:票号:15
窗口3:票号:14
窗口3:票号:13
窗口3:票号:12
窗口3:票号:11
窗口3:票号:10
窗口3:票号:9
窗口3:票号:8
窗口3:票号:7
窗口3:票号:6
窗口3:票号:5
窗口3:票号:4
窗口3:票号:3
窗口3:票号:2
窗口3:票号:1

Process finished with exit code 0

3.3 Runnable(同步方法)

如果操作共享数据的代码完整的声明在一个方法中,可以将这个方法声明为同步的

package JavaPackage_13;

public class JavaCode {
    public static void main(String[] args) {
        Window window = new Window();
        Thread thread1 = new Thread(window);
        Thread thread2 = new Thread(window);
        Thread thread3 = new Thread(window);
        thread1.setName("窗口1");
        thread2.setName("窗口2");
        thread3.setName("窗口3");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

class Window implements Runnable {

    private int ticket = 100;

    @Override
    public void run() {    //public synchronized void run() synchronized包含的同步代码:不能包多也不能包少
        while (true) {
            show();
        }
    }
    private synchronized void show(){ // 同步监视器:this
        if (ticket > 0) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":票号:" + ticket--);
        }
    }
}

3.4 Thread(同步方法)

package JavaPackage_13;

public class JavaCode {
    public static void main(String[] args) {
        Window window1 = new Window();
        Window window2 = new Window();
        Window window3 = new Window();
        window1.setName("窗口1");
        window2.setName("窗口2");
        window3.setName("窗口3");
        window1.start();
        window2.start();
        window3.start();
    }
}

class Window extends Thread {

    private static int ticket = 100;

    @Override
    public void run() {
        while (true) {
            show();
        }
    }

    public static synchronized void show(){ // 同步监视器:Window.class
        if (ticket > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":票号:" + ticket--);
        }
    }
}

3.5 Lock解决线程安全问题

package JavaPackage_13;

import java.util.concurrent.locks.ReentrantLock;

public class JavaCode {
    public static void main(String[] args) {
        Window window1 = new Window();
        Window window2 = new Window();
        Window window3 = new Window();
        window1.setName("窗口1");
        window2.setName("窗口2");
        window3.setName("窗口3");
        window1.start();
        window2.start();
        window3.start();
    }
}

class Window extends Thread {

    private static int ticket = 100;
    private static ReentrantLock lock = new ReentrantLock(true); // 公平锁

    @Override
    public void run() {
        while (true) {
            try {
                //调用lock()
                lock.lock();
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":票号:" + ticket--);
                } else {
                    break;
                }
            } finally {
                //调用unlock()
                lock.unlock();
            }
        }
    }
}


请添加图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苡荏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值