《Java并发编程之美》第一章笔记

java线程创建

1.为实现 Runnabl 接口的 run 方法

public class ThreadTest { 
    public static class MyThread ext ends Thread { 
        @Override 
        public void run(){ 
            System out print ("I am a child thread"); 
        }
        public static void main (String[] args) { 
            //创建线程
            MyThread thread= new MyThread (); 
            // 启动线程
            thread .start(); 
        }
}

2.继承 hread 重写 run 方法

public static class RunableTask implements Runnable{ 
    @Override 
    public void run() { 
        System.out.println ("I am a child thread" );
    }
    public static void main(String[] args) throws terruptedException{
        RunableTask task =new RunableTask(); 
        new Thread(task).start(); 
        new Thread(task).start(); 
    }
}

3.使用futureTask方式

//创建任务类,类似runable
public stat class CallerTask implements Callable<String>{
    @Override
    public String call () throws Except on { 
        return "hello ”;
    }
public static void main(String[] args) throws InterruptedException { 
    // 创建异步任务
    FutureTask<String> futureTask =new FutureTask<>(new CallerTask()) ; 
    //启动线程
    new Thread(futureTask). start () ; 
    try { 
        //等待任务执行完毕,并返回结果
        String result = futureTask.get (); 
        System out printl口( result );
    }
    catch (ExecutionExcept on e) { 
    	e.printStackTrace() ;
    }
}

小结:使用继承方式的好处是方便传参,你可以在子类里面添加成员变量 ,通过 set 方法设置参数或者通过构造函数进行传递,而如果使用 Runnable 方式,则只能使用主线程里面被声明为 final 变量。不好的地方是 Java 支持多继承,如果继承了 Thread 类, 那么子 不能再继承其他 ,而 Runnable 则没有这个限制 。前两种方式都没办法拿到任务 的返回结果,但是 futuretask 方式可以.

线程通知与等待

wait()函数

当一个线程调用一个共享变量的wait()方法时,该线程会阻塞挂起直到(释放锁)

①其他线程调用该共享对象的notify()或notifyAll()方法

②其他线程调用该线程的interrupt()方法,该线程抛出InterruptedException异常返回

调用wait方法前线程需要事先获取该对象的监视器锁(使用synchronied)

wait(long timeout)函数:该方法相 wait() 方法多了一个超时参数,它的不同之处在于,如果一个线程调用共 享对象的该方法挂起后 没有在指定的 timeout ms 内被其线程调用该共享变量的 notify () 或者 notifyAll () 方法唤醒,那么该函数还是会因为超时而返回。如果将 timeout 置为0则和 wait 方法效果一样,因为在 wait 方法内部就是调用了 wait 需要注意的是, 如果在调用该函数时传递了一个负的timeout 会抛出IllegalArgumentException异常

wait(long timeout, int nanos )函数:在其内部调用的是 wait(long timeout)函数,只有在 nanos>0 时才使参数 timeout 递增1.

notify函数和notifyAll函数

notify时唤醒一个在该共享变量上调用wait系列方法被挂起的线程。notifyAll时唤醒所有。

等待线程执行终止的 join 方法

等待线程完成才进行下面代码

另外,线程调用线程 join 方法后会被阻塞,当其它线程调用了线程 interrrupt()方法中断了线程 时,线程会抛出 InterruptedException 异常而返回。

让线程睡觉的sleep方法

调用sleep线程会让出指定时间的执行权,不参与CPU调度,不过锁还是持有不让出,时间一到线程处于就绪状态

,如果一个线程中断了它,会在sleep方法处抛出异常。如果sleep传递参数为负,会抛IllegalArgumentException异常。

让出CPU执行权的yield方法

Thread 有一个静态 yield 方法,当一个线程调用 yield 方法时,实际就是在暗示线程调度器当前线程请求让出自己 CPU 使用,但是线程调度器可以无条件忽略这个暗示。我们知道操作系统是为每个线程分配一个时间片来占有CPU 的, 正常情况下当一个 线程分配给自己的时间片使用完后,线程调度器才会进行下一轮的线程调度,而当一个线程调用了 Thread 类的静态方法 yield 时,是在告诉线程调度器自己占有的时间片中还没 有使用完的部分自己不想使用了,这暗示线程调度器现在就可以进行下一轮的线程调度

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

总结 :sleep 和yield 方法的区别在于,当线程调用 sleep 方法时调用线程会被阻塞挂起指定的时间,在这期间线程调度器不会去调度该线程 ;而调用 yield方法时,线程只是让出自己剩余的时间片,并没有被阻塞挂起,而是处于就绪状态,线程调度器下一次调度时就有可能调度到当前线程执行

线程中断

void interrupt()方法:中断线程A。线程A运行时设置标志位,如线程A调用了wait系列函数、join方法或者sleep方法而被阻塞,则会抛出异常并返回。

boolean isInterrupted()方法:检测当前线程是否中断,是返回true,否返回false

boolean interrupted()方法检测当前线程是否中断,是返回true,否返回false,并重置当前线程中断标志,是Thread一个静态方法

守护进程与用户进程

Java 中的线程分为两类,分别为 daemon 线程(守护线程)和 user 线程(用户线程)。 在JVM 启动会调用 main 函数, main 数所在的线程就是一个用户线程,其实在 JVM 内部同时-还启动了好多守护线程, 比如垃圾回收线程。那么守 线程和用户线程有什么 区别呢?区别之一是当最后一个非守护线程结束时, JVM 正常退出,而不管当前是否有守护线程,也就是说守护线程是否结束并不影响 JVM 退出。言外之意,只要有一个用 户线程还没结束 正常情况下 JVM 就不会退出。

创建守护进程:

public static void main(String[] args) { 
    Thread daemonThread = new Threadnew Runnable() { 
    public void run() {
        
    } 
    }) ;
    //设置 为守护线程
    daemonThread.setDaemon(true) ; 
    daemonThread.start (); 
}

ThredLocal

当创建一个变量后 每个线程对其进行访问的时候访问的是自己线程的变量

ThreadLocal JDK 包提供的,它提供了线程本地变量,也就是如果你创建了 ThreadLocal ,那么访问这个变量的每个线程都会有这个变量的一个本地副本

static ThreadLocal<String> localVariable = new ThreadLocal<> () ; 

三个方法:

void set(T value)

T get()

void remove()

ThreadLocal不支持继承性,子线程不可访问父线程的本地变量,可以用InheritableThreadLocal类

public static ThreadLocal<String> threadLocal = new InheritableThreadLocal<String> ();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值