java 线程(Thread.Join(),上下文切换,线程的run和start)

最近在看《java并发编程的艺术》,更多是随笔和摘要书中内容

目录

1.Thread.join()

2. 线程的线程状态转换图

3. Thread.start 和run方法

4. 实现线程的几种方式?

5.线程上下文切换

5.1 无锁并发编程

5.2 CAS算法

5.3 使用最少线程

5.4 协程

6. 线程有哪些状态?

7. Thread.yield();


1.Thread.join()

在父线程创建并调用子线程的时候,如果调用join()方法,那么就会让父线程等待子线程结束然后在继续运行~

例子:

package lock;

public class ConcurrencyTest {
    private static final long count = 100001;

    public static void main(String[] args) throws InterruptedException {
        concurrency();
        serial();
    }

    //并发执行
    private static void concurrency() throws InterruptedException {

        long start = System.currentTimeMillis();
        Thread thread = new Thread(
                () -> {
                    int a = 0;
                    for (int i = 0; i < count; i++) {
                        a += 5;
                    }
                    System.out.println("concurrency: a = " + a);
                }
        );
        thread.start();
        int b = 0;
        for (int i = 0; i < count; i++) {
            b--;
        }
        thread.join();
        long time = System.currentTimeMillis() - start;
        System.out.println("concurrency :" + time + "ms,b=" + b);
    }

    //串行执行
    private static void serial() {
        long start = System.currentTimeMillis();

        int a = 0;
        for (int i = 0; i < count; i++) {
            a += 5;
        }
        System.out.println("serial: a = " + a);

        int b = 0;
        for (int i = 0; i < count; i++) {
            b--;
        }
        long time = System.currentTimeMillis() - start;
        System.out.println("serial :" + time + "ms,b=" + b);

    }

}

运行结果:concurrency: a = 500005
concurrency :100ms,b=-100001
serial: a = 500005
serial :5ms,b=-100001

2. 线程的线程状态转换图

Java-thread-state-transition

转自:https://www.cnblogs.com/huangzejun/p/7908898.html

3. Thread.start 和run方法

start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法。start()不能被重复调用。
run()   : run()就和普通的成员方法一样,可以被重复调用。单独调用run()的话,会在当前线程中执行run(),而并不会启动新线程!

下面以代码来进行说明。

class MyThread extends Thread{  
    public void run(){
        ...
    } 
};
MyThread mythread = new MyThread();

mythread.start()会启动一个新线程,并在新线程中运行run()方法。
而mythread.run()则会直接在当前线程中运行run()方法,并不会启动一个新线程来运行run()。

很清晰明了了~

转:https://www.cnblogs.com/skywang12345/p/3479083.html

4. 实现线程的几种方式?

1.继承Thread类

2.实现Runnable接口(new Thread(new Runnable(){})

3.通过Callable和FutureTask创建线程

4.通过线程池创建线程

最后都得用Thread类来接收

见自己写的:https://blog.csdn.net/pmdream/article/details/88535026

5.线程上下文切换

单核处理器也能实现多线程。多线程就是通过每个线程争夺CPU分配的时间片来实现多线程的。

时间片就是CPU分配给每个线程的时间,很短所以感受不到不停地切换线程执行。

在时间片切换之前会保存上一个任务的状态,以便任务执行下次切回来执行还能够加载这个任务的状态。

任务从保存到在加载的过程就是一次上下文切换,

所以多线程并不一定就是很快的~

减少上下文切换的方法无锁并发编程、CAS算法、使用最少线程和使用协程

5.1 无锁并发编程

无锁并发编程,多线程竞争锁的时候,会引起上下文切换,所以多线程处理数据的时候,可以用一些方法避免使用锁。

如将数据的ID按照Hash算法取模分段,不同线程处理不同段的数据(避免争抢公共资源)

问题:多线程是怎么竞争锁的?

5.2 CAS算法

Java的Atomic包使用CAS算法来更新数据,而不需要加锁。

5.3 使用最少线程

没必要创建不必要的线程,因为人物很少的时候创建线程来处理,就会有很多线程在等待状态

5.4 协程

单线程里实现多任务的调度,并在单线程中维持多个任务间的切换

6. 线程有哪些状态?

1. 新建(NEW):新创建了一个线程对象。

2. 可运行(RUNNABLE):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。

3. 运行(RUNNING):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。
4. 阻塞(BLOCKED):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种: 

(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
(三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。

5. 死亡(DEAD):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

转:https://blog.csdn.net/xingjing1226/article/details/81977129

7. Thread.yield();

        Java线程中的Thread.yield( )方法,译为线程让步。顾名思义,就是说当一个线程使用了这个方法之后,它就会把自己CPU执行的时间让掉,

让自己或者其它的线程运行,注意是让自己或者其他线程运行,并不是单纯的让给其他线程。

        yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保

证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!

      举个例子:一帮朋友在排队上公交车,轮到Yield的时候,他突然说:我不想先上去了,咱们大家来竞赛上公交车。然后所有人就一块冲向公交车,

有可能是其他人先上车了,也有可能是Yield先上车了。

     但是线程是有优先级的,优先级越高的人,就一定能第一个上车吗?这是不一定的,优先级高的人仅仅只是第一个上车的概率大了一点而已,

最终第一个上车的,也有可能是优先级最低的人。并且所谓的优先级执行,是在大量执行次数中才能体现出来的。

转:https://www.cnblogs.com/java-spring/p/8309931.html

8. synchronized

实现锁的 功能

 

9. 读写锁?

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值