《Java并发编程之美》读书笔记及代码-第一章

1.1 什么是线程

进程:系统进行资源分配的和调度的基本单位。

线程:CPU分配的基本单位。

程序计数器:一块内存区域,用来记录线程当前要执行的指令地址。

堆:主要存放使用new操作创建的对象实例。

方法区:用来存放JVM加载的类、常量及静态变量等信息。

1.2 线程的创建与运行

Java中有三种方式创建线程。

继承Thread类方式的实现:

public class ThreadTest {
    // 继承Thread类并重写run方法
    public static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("I am a child Thread");
        }
    }

    public static void main(String[] args) {
        // 创建线程
        MyThread thread = new MyThread();
        // 启动线程
        thread.start();
    }
}

好处:在run()方法中获取当前线程直接使用this就可以了,无需使用Thread.currentThread()方法。

不好:A.Java不支持多继承,如果继承了Thread类,就不能再继承其他类。

B.任务与代码没有分离,当多个线程执行一样的任务时需要多份任务代码。

Runnable接口的run方法实现:

public class ThreadTest {
    public static class RunnableTask implements Runnable {

        @Override
        public void run() {
            System.out.println("I am a child Thread implements Runnable");
        }
    }

    public static void main(String[] args) {
        RunnableTask task = new RunnableTask();
        new Thread(task).start();
        new Thread(task).start();
    }
}

前两种方式都有一个缺点,就是任务没有返回值。

FutureTask的方式:

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

// 创建任务类,类似Runnable
public class CallerTask implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "hello";
    }

    public static void main(String[] args) {
        // 创建异步任务
        FutureTask<String> futureTask = new FutureTask<>(new CallerTask());
        // 启动线程
        new Thread(futureTask).start();
        try {
            // 等待任务执行完毕,并返回结果
            String result = futureTask.get();
            System.out.println(result);
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

1.3 线程通知与等待

public class WaitNotifyTest {
    // 创建资源
    private static volatile Object resourceA = new Object();
    private static volatile Object resourceB = new Object();

    public static void main(String[] args) throws InterruptedException {
        // 创建线程
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 获取resourceA共享资源的监视器锁
                    synchronized (resourceA) {
                        System.out.println("threadA get resourceA lock");
                        // 获取resourceB共享资源的监视器锁
                        synchronized (resourceB) {
                            System.out.println("threadA get resourceB lock");
                            // 线程A阻塞,并释放获取到的resourceA的锁
                            System.out.println("threadA release resourceA lock");
                            resourceA.wait();
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        // 创建线程
        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 休眠一秒
                    Thread.sleep(1000);
                    // 获取resourceA共享资源的监视器锁
                    synchronized (resourceA) {
                        System.out.println("threadB get resourceA lock");
                        System.out.println("threadB try get resourceB lock...");
                        // 获取resourceB共享资源的监视器锁
                        synchronized (resourceB) {
                            System.out.println("threadB get resourceB lock");
                            // 线程B阻塞,并释放获取到的resourceA的锁
                            System.out.println("threadB release resourceA lock");
                            resourceA.wait();
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        // 启动线程
        threadA.start();
        threadB.start();

        // 等待两个线程结束
        threadA.join();
        threadB.join();
        System.out.println("main over");
    }
}

当线程调用共享对象时的wait()方法时,当前线程只会释放当前共享对象的锁,当前线程持有的其他共享对象的监视器并不会被释放。

notify()方法只会激活阻塞集合里面的一个线程。notifyAll()只会唤醒调用这个方法前调用了wait系列函数而被放入共享变量等待集合里面的线程。

public class WaitNotifyAllTest {
    // 创建资源
    private static volatile Object resourceA = new Object();

    public static void main(String[] args) throws InterruptedException {
        // 创建线程
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                // 获取resourceA共享资源的监视器锁
                synchronized (resourceA) {
                    System.out.println("threadA get resourceA lock");
                    try {
                        System.out.println("threadA begin wait");
                        resourceA.wait();
                        System.out.println("threadA end wait");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        // 创建线程
        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resourceA) {
                    System.out.println("threadB get resourceA lock");
                    try {
                        System.out.println("threadB begin wait");
                        resourceA.wait();
                        System.out.println("threadB end wait");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        // 创建线程
        Thread threadC = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resourceA) {
                    System.out.println("threadC begin notify");
                    resourceA.notify();
                }
            }
        });
        // 启动线程
        threadA.start();
        threadB.start();

        Thread.sleep(1000);
        threadC.start();

        // 等待线程结束
        threadA.join();
        threadB.join();
        threadC.join();

        System.out.println("main over");
    }
}

1.6让出CPU执行权的yield方法

当一个线程调用yield方法时,当前线程会让出CPU使用权,然后处于就绪状态,线程调度器会从线程就绪队列里面获取一个线程优先级最高的线程,当然也有可能会调度到刚刚让出CPU的那个线程来获取CPU的执行权。

public class YieldTest implements Runnable {
    YieldTest() {
        // 创建并启动线程
        Thread t = new Thread(this);
        t.start();
    }
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            // 当i=0时让出CPU执行权,放弃时间片,进行下一轮调度
            if ((i%5) == 0) {
                System.out.println(Thread.currentThread() + "yield cpu...");
                // 当前线程让出CPU执行权,放弃时间片,进行下一轮调度
                Thread.yield();
            }
        }
        System.out.println(Thread.currentThread() + " is over");
    }

    public static void main(String[] args) {
        new YieldTest();
        new YieldTest();
        new YieldTest();
    }
}

1.7 线程中断

public class SleepInterruptTest {
    public static void main(String[] args) throws InterruptedException {
        Thread threadOne = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("threadOne begin sleep for 2000 seconds");
                    Thread.sleep((2000000));
                    System.out.println("threadOne awaking");
                } catch (InterruptedException e) {
                    System.out.println("threadOne is interrupted while sleeping");
                    return ;
                }
                System.out.println("threadOne-leaving normally");
            }
        });
        // 启动线程
        threadOne.start();
        // 确保子线程进入休眠状态
        Thread.sleep(1000);
        // 打断子线程的休眠,让子线程从sleep函数返回
        threadOne.interrupt();
        // 等待子线程执行完毕
        threadOne.join();
        System.out.println("main thread is over");
    }
}

1.9线程死锁

死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的互相等待的现象,在无外力作用的情况下,这些线程会一直相互等待而无法继续运行下去。

典型的死锁:

public class DeadLockTest {
    // 创建资源
    private static Object resourceA = new Object();
    private static Object resourceB = new Object();

    public static void main(String[] args) {
        // 创建线程A
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resourceA) {
                    System.out.println(Thread.currentThread().getName() + " get resourceA");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " waiting get resourceB");

                    synchronized (resourceB) {
                        System.out.println(Thread.currentThread().getName() + " get resourceB");
                    }
                }
            }
        },"Thread-A");
        // 创建线程B
        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resourceB) {
                    System.out.println(Thread.currentThread().getName() + " get resourceB");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " waiting get resourceA");

                    synchronized (resourceA) {
                        System.out.println(Thread.currentThread().getName() + " get resourceA");
                    }
                }
            }
        },"Thread-B");

        // 启动线程
        threadA.start();
        threadB.start();
    }
}

1.11 ThreadLocal

public class ThreadLocalTest {
    // (1) print函数
    static void print(String str) {
        // 1.1 打印当前线程本地内存中的localVariable变量的值
        System.out.println(str + ":" + localVariable.get());
        // 1.2 清除当前线程本地内存中的localVariable变量
        localVariable.remove();
    }
    // (2) 创建ThreadLocal变量
    static ThreadLocal<String> localVariable = new ThreadLocal<>();

    public static void main(String[] args) {
        // (3) 创建线程one
        Thread threadOne = new Thread(new Runnable() {
            @Override
            public void run() {
                // 3.1 设置线程One中本地变量localVariable的值
                localVariable.set("threadOne local variable");
                // 3.2 调用打印函数
                print("threadOne");
                // 3.3 打印本地变量值
                System.out.println("threadOne remove after" + ":" + localVariable.get());
            }
        });
        // (4) 创建线程two
        Thread threadTwo = new Thread(new Runnable() {
            @Override
            public void run() {
                // 4.1 设置线程Two中本地变量localVariable的值
                localVariable.set("threadTwo local variable");
                // 4.2 调用打印函数
                print("threadTwo");
                // 4.3 打印本地变量值
                System.out.println("threadTwo remove after" + ":" + localVariable.get());
            }
        });
        // (5) 启动线程
        threadOne.start();
        threadTwo.start();

    }
}
InheritableThreadLocal
public class TestThreadLocal {
    // (1) 创建线程变量
    public static ThreadLocal<String> threadLocal = new InheritableThreadLocal<>();

    public static void main(String[] args) {
        // (2) 设置线程变量
        threadLocal.set("hello world");
        // (3) 启动子线程
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                // (4) 子线程输出线程变量的值
                System.out.println("thread:" + threadLocal.get());
            }
        });
        thread.start();

        // (5) 主线程输出线程变量的值
        System.out.println("main:" + threadLocal.get());

    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值