首页技术文章正文

多线程1【黑马java培训】

更新时间:2019年07月26日 11时17分37秒 来源:黑马程序员论坛



            多线程1

1.1什么是线程
  现代操作系统在运行一个程序时,会为其创建一个进程。例如,启动一个java程序,操作系统就会创建一个java的进程。现代操作系统调度的最小单位是线程,也叫轻量级进程,一个进程同时执行和创建多个任务,通常,每一个任务称为一个线程。
这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量(并发问题的根源)。处理器在这些线程上高速的切换(CPU分配时间片给每个线程),给人并发处理的感觉。
1.2为什么要使用线程
(1)更多的处理器核心
     随着处理器的核心越来越多,现在大多数计算机比以往更加擅长处理并发。线程是大多数操作系统的最小单元,而一个线程在同一时刻只能在一个处理器核心上运行,试想一下,一个单线程程序在运行时只能使用一个处理器核心,那么再多的处理器核心也无法加入,也无法提升程序的执行效率。如果改程序使用多线程技术,将计算逻辑分配到多个处理器核心上,就会显著的减少程序的处理时间,并随着更多处理器核心的加入而变得更有效率。
(2)更快的响应
  有时候我们会编写一些较为复杂的代码(指复杂业务),例如:一笔订单的创建,它包括插入订单数据、订单快照的生成、发送邮件通知卖家和记录货物销售的数量等。用户从点击“订购”开始,就需要等待这些操作全部完成才能看到结果,这么多操作如何能让它更快速的完成。
可以使用多线程技术,将数据一致性不强的操作派发给其他线程处理(也可以使用消息队列),如生成订单快照,发送邮件等。这样做的好处是响应用户请求的线程可以尽快的处理完成,缩短响应时间,提升用户体验。
1.3线程优先级
  每一个线程都有优先级,每当程序调度器有机会选择新的线程,它首先选择的是优先级高的线程,默认情况下一个线程继承它父线程的优先级,可以使用setPriority提高或降低一个线程的优先级,可以设置110之间的任何值。但是优先级的高度依赖于系统,线程优先级被映射到宿主主机,优先级根据主机增加或减少。
运行下面可以看到线程优先级没有生效,优先级1和优先级10的结果非常相似,这表示程序的正确性不能依赖线程的优先级高低。
代码:
[Java] 纯文本查看 复制代码
public class Priority {
        private static volatile boolean notStart=true;
        private static volatile boolean notEnd=true;
        public static void main(String[] args) throws InterruptedException {
                List<Job> jobs = new ArrayList<Job>();
                for (int i = 0; i < 10; i++) {
                        //如果i小于5那个i=1,如果大于51=10
                        int priority =i < 5 ? Thread.MIN_PRIORITY:Thread.MAX_PRIORITY;
                        Job job = new Job(priority);//初始化job
                        jobs.add(job);
                        Thread thread = new Thread(job, "Thread"+i);//创建线程
                        thread.setPriority(priority);//设置优先级
                        thread.start();//启动线程
                }
                notStart=false;
                TimeUnit.SECONDS.sleep(10);
                notEnd=false;
                for (Job job : jobs) {
                        System.out.println("job priority:"+job.priority+"== count:"+job.jobCount);
                }
        }
        static class Job implements Runnable{
                private int priority;
                private long jobCount;
                public Job(int priority) {
                        this.priority=priority;
                }
                @Override
                public void run() {
                        while (notStart) {
                                Thread.yield();
                        }
                        while (notEnd) {
                                Thread.yield();
                                jobCount++;
                        }       
                }
        }
}



1.4线程的状态
Java线程在运行的生命周期中可能处于6中不同的状态,在给定的一个时刻,线程只能处于一个状态。
new
初始状态,线程被构造,但是还没有调用start()方法
runnable
运行状态,一旦调用start方法,线程处于runnable状态,一个可运行的线程可能正在运行也可能没有运行,这取决去操作其他给线程提供的运行时间。
blocked
阻塞状态,当一个线程处于被阻塞和等待状态,它不运行任何代码且消耗的资源最少,当一个线程视图获取一个内部对象锁,而该锁被其他对象持有,则该线程进入阻塞状态,当所有线程释放该锁,并且线程调度器允许本线程持有它的时候,该线程变成非阻塞状态。
Waiting
等待状态,表示线程进入等待状态,该状态表示当前线程需要等待其他线程做出一些特定的动作(通知或中断)
timed Waiting
计时等待,有几个方法有一个超时参数,调用它们导致线程进入计时等待状态,这一状态将保持到超时期满或者接收到适当的通知,带有超时参数方法有Tread.sleepObject.waitTread.JionLock.Trylock以及Condition.await的计时版。
Terminated
终止状态,线程因如下两个原因之一而被中止:
1.run方法正常退出而自然消亡。
2.因为一个没有捕获的异常终止了run方法而意外死亡。


线程的状态变迁:
1.5 Daemon线程
  可以通过调用setDaemon将一个线程转换为守护线程,守护线程唯一的用处就是为其他线程提供服务,比如计时线程就是一个例子,它定时发送信号给其他线程或清空高速缓存项的线程,但只剩下一个守护线程,那么守护线程就不需要存在,虚拟机就会退出。
2 启动和终止线程


2.1 构造线程
在线程运行之前首先需要构造一个线程对象,线程对象在构造的时候需要提供线程所需的属性。如线程所属的线程组、线程优先级、是否是Daemon线程等信息。
2.2启动线程
    线程对象在初始化完成之后,调用start()方法就可以启动线程,当前线程(即parent线程)同步告知java虚拟机,只要线程调度器空闲,应立即启动调用start()方法的线程。
注意:在启动一个线程前最好个线程起一个名字,方便于问题的排查
2.3理解中断
   中断好比其他线程对该线程打了个招呼,其他线程通过调用该线程的interrupt()方法对其进行中断(线程的默认状态是false),线程标识被重置为true,表示该线程的状态为中断。
   线程通过isInterrupted()来判断是否被中断,也可以调用静态方法Thread.interrupted()对当前线程进行复位。在调用isInterrupted依旧会返回false,当前线程调用interruped()方法返回线程中断状态,并且会将线程中断状态重置为false。详情请看API.
中断测试:
[Java] 纯文本查看 复制代码
public class InterruptedTest implements Runnable{
private static Thread thread;
@Test
    public void test(){
thread = new Thread(new InterruptedTest(),"InterruptedTest");
thread.setDaemon(true);
thread.start();
}
@Override
public void run() {
thread.interrupt();//中断线程
boolean interrupted2 = thread.interrupted();//获取线程状态,并将线程状态重置为false
System.out.println(interrupted2);//被中断true,
boolean interrupted = Thread.interrupted();//获取当前状态,false
System.out.println(interrupted);
boolean interrupted3 = Thread.interrupted();//获取当前状态,false
System.out.println(interrupted3);
}
}

2.4过期的suspend()resume()stop()
  这些API都是过期的不建议使用,以suspend()方法为例,在调用后线程不会释放占有的资源(比如锁),而是带着资源进入休眠状态,如果线程死亡就会出现死锁问题。Stop()方法在终结线程时不会保证线程的资源正常释放。
2.5安全地终止线程
   使用boolean变量手动控制线程,是否需要停止任务并终止该线程。
  
[Java] 纯文本查看 复制代码
public class Shutdown {[/align]    public static void main(String[] args) throws Exception {
        Runner one = new Runner();
        Thread countThread = new Thread(one, "CountThread");
        countThread.start();
        // 睡眠1秒,main线程对CountThread进行中断,使CountThread能够感知中断而结束
        TimeUnit.SECONDS.sleep(1);
        countThread.interrupt();
        Runner two = new Runner();
        countThread = new Thread(two, "CountThread");
        countThread.start();
        // 睡眠1秒,main线程对Runner two进行取消,使CountThread能够感知on为false而结束
        TimeUnit.SECONDS.sleep(1);
        two.cancel();
    }
    private static class Runner implements Runnable {
        private long             i;
        private volatile boolean on = true;
        @Override
        public void run() {
            while (on && !Thread.currentThread().isInterrupted()) {
                i++;
            }
            System.out.println("Count i = " + i);
        }
        public void cancel() {
            on = false;
        }
    }
}


推荐了解热门学科

java培训 Python人工智能 Web前端培训 PHP培训
区块链培训 影视制作培训 C++培训 产品经理培训
UI设计培训 新媒体培训 产品经理培训 Linux运维
大数据培训 智能机器人软件开发




传智播客是一家致力于培养高素质软件开发人才的科技公司“黑马程序员”是传智播客旗下高端IT教育品牌。自“黑马程序员”成立以来,教学研发团队一直致力于打造精品课程资源,不断在产、学、研3个层面创新自己的执教理念与教学方针,并集中“黑马程序员”的优势力量,针对性地出版了计算机系列教材50多册,制作教学视频数+套,发表各类技术文章数百篇。

传智播客从未停止思考

传智播客副总裁毕向东在2019IT培训行业变革大会提到,“传智播客意识到企业的用人需求已经从初级程序员升级到中高级程序员,具备多领域、多行业项目经验的人才成为企业用人的首选。”

中级程序员和初级程序员的差别在哪里?
项目经验。毕向东表示,“中级程序员和初级程序员最大的差别在于中级程序员比初级程序员多了三四年的工作经验,从而多出了更多的项目经验。“为此,传智播客研究院引进曾在知名IT企业如阿里、IBM就职的高级技术专家,集中研发面向中高级程序员的课程,用以满足企业用人需求,尽快补全IT行业所需的人才缺口。

何为中高级程序员课程?

传智播客进行了定义。中高级程序员课程,是在当前主流的初级程序员课程的基础上,增加多领域多行业的含金量项目,从技术的广度和深度上进行拓展“我们希望用5年的时间,打造上百个高含金量的项目,覆盖主流的32个行业。”传智播客课程研发总监于洋表示。




黑马程序员热门视频教程【点击播放】

Python入门教程完整版(懂中文就能学会) 零起点打开Java世界的大门
C++| 匠心之作 从0到1入门学编程 PHP|零基础入门开发者编程核心技术
Web前端入门教程_Web前端html+css+JavaScript 软件测试入门到精通


在线咨询 我要报名
和我们在线交谈!