Java初学者需要对多线程的理解与深化

    科技2022-08-29  104

    从浅入深对Java多线程的剖析与理解

    1、什么是线程,线程与进程又有什么区别?

            进程顾名思义就是系统中正在运行的服务,我们的每一个程序的运行都有一个进程在系统的环境下进行运行。进程可以手动的进行杀死,当将进程进行杀死时,程序自然而然的就停止运行了,我们平常所用的任务管理器就是专门用来管理进程的。         线程是指进程中单一顺序的执行流。线程共享相同的地址空间并共同构成一个大的进程。线程间的通信简单而有效,上下文切换非常快,他们是同一个进程中的两个部分之间所进行的切换。每个线程彼此独立执行,一个程序可以同时使用多个线程来完成不同的任务。一般用户在使用多线程时并不需要考虑底层处理的详细细节。例如:         (1)、一个Web浏览器边下载数据边显示已经到达的数据。这是因为有一个线程在执行下载数据并且通知另一个线程有更多的数据已经到达,另一个线程则整理和显示已经到达的信息。         (2)、许多编辑器能够实时检查英文拼写的错误,即当用户输入字符时,该编辑器能够立即自动分析文本和标出错误的单词。这是因为有一个线程在接收文本所输入的字符,而另一个线程在“读入”输入的字符,分析并标记处错误的部分。功能更强的编辑器还可以进行语法检查。

    2、多线程又是什么?

            多线程程序是指一个程序中包含有多个执行流,多线程是实现并发机制的一种有效手段。从逻辑的观点来看,多线程意味一个程序的多行语句同时执行,但是多线程并不等于多次启动一个程序,操作系统也不把每个线程当做独立的进程来对待。因此如果很好地利用线程,可以大大简化应用程序设计,让编程人员大大的简化自己所写的代码。         在传统的单进程环境下,用户必须等待一个任务完成后才能进行下一个任务。即使大部分时间空闲,也只能按部就班的工作,绝对不能插队。多线程可以解决这个问题,让用户不在等待。所以说多线程这个机制在许多为用户服务的软件中有着重要的作用。

    3、思考一个问题,对于单核CPU来说,可以做到真正的多线程并发吗?

            单核的CPU不能做到真正的多线程并发,但是例如我们进行玩英雄联盟的时候,一边进行游戏音乐的播放、一边进行游戏人物的走动,这让我们误以为是多线程,其实这不是真正的多线程。这是因为CPU的速度处理速度快,在多个线程之间来回切换,让我们有了一边进行音乐播放,一边进行玩游戏的错觉。         这就像我们小时候看的播放胶卷的电影,其实正常来说,这种电影是一个一个图画进行播放的,但是对于人类来说,就像是在看一组连续的动画一样。这说明人类的反应速度很慢,就像用针扎手一样,人类“很长时间”才能感觉到疼痛,但是计算机不一样,计算机已经在这个时间段内进行上亿的计算了。

    4、Java语言中,实现多线程的方式是什么?

            Java中已经把多线程机制实现了,我们只需要继承或者实现就可以了。         第一种方式:编写一个类,实现java.lang.Runnable接口,并重写run()方法。         第二种方式:编写一个类,继承java.lang.Thread类,并重写run()方法。         注意:上面两种方法,建议使用第一种方法,因为Java可以实现多接口,但是只能实现单继承,我们实现了一个接口,还可以去继承其他的类,更加灵活。

    5、谈一谈线程对象的声明周期?

            新建状态         就绪状态         运行状态         阻塞状态         死亡状态

    6、多线程环境下,数据的安全问题

            当多线程并发、有共享数据,并且共享数据有修改的行为时会发生数据线程安全问题。那么当产生这个问题时,应该怎么解决呢?只要让线程排队执行,这种机制被称为线程同步机制,实际上就是线程不能并发的去执行了,只能排队执行。但是线程同步会失去一部分效率,但是为了数据的安全,这种做法必须执行。因为只有数据安全了,我们才可以谈效率。         说到线程同步这块,涉及到两个专业术语:         (1)、同步编程模型:                      线程A和线程B,线程A要执行的时候必须等待线程B执行完毕,或者说线程B执行的之后必须要等待线程A执行完毕,两个线程之间形成一种等待关系,效率较低,线程排队执行。同步就是排队         (2)、异步编程模型:                      线程A和线程B,线程A执行的时候不用管线程B是否执行,线程B执行的时候不用管线程A是否执行,各自执行各自的。效率较高,线程并发执行。异步就是并发

    7、Java中的变量与线程安全的关系

            (1)、局部变量:                      实例变量在栈中,一个线程一个栈,所以栈不会存在线程安全问题。         (2)、实例变量:                      实例变量在堆中,堆在JVM虚拟机中只有一个,所以会存在线程安全问题。         (3)、静态变量:                      静态变量在方法区中,方法区在JVM中也只有一个,所以会存在线程安全问题。

    8、局部变量的使用与集合的线程安全与否?

            局部变量是不会发生线程不安全的,所以修饰局部变量建议使用StringBuilder,不建议使用StringBuffer,因为StringBuffer相对于局部变量来说效率较低。         (1)、ArrayList是非线程安全的。         (2)、Vector是线程安全的。         (3)、HashMap、HashSet是非线程安全的。         (4)、HashTable是线程安全的。

    9、线程同步synchronized的写法与介绍

            (1)、使用同步代码块:                      synchronized(线程共享对象) {同步代码块}         (2)、在实例方法上使用synchronized:                      表示共享对象一定是this,并且同步代码块是整合方法体。         (3)、在静态方法上使用synchronized:                      表示创建类锁,类锁永远只有一把,就算创建了100个对象,也只有一把类锁。         注意:类锁与对象锁的区别?         对象锁:一个对象一把锁,100个对象100把锁。         类锁:一个对象一把锁,100个对象也是只有一把锁。

    10、谈谈我们程序人员在以后开发中如何解决线程安全问题?

            是一上来就使用线程同步吗?当然不是了,使用线程同步会让程序的执行效率下降,降低用户的体验,只有在不得已的情况下,我们才可以选择线程同步。那么如何解决线程安全问题呢?         (1)、尽量使用局部变量代替实例变量和静态变量。         (2)、如果不得不使用实例变量,那么就考虑在方法中使用实例变量new出多个对象,这样实例变量的内存就不会共享了,1个线程一个对象,100个线程100个对象,这样可以解决线程安全·问题了。         (3)、如果不能使用局部变量,也不能创建多个对象,那么就只能使用线程同步机制synchronized了。

    11、线程这块还有哪些需要我们知道的线程?

            (1)、守护线程:                      Java中的线程分为两大类:一类是用户线程(主线程main方法是一个用户线程)、一类是守护线程(也叫做后台线程,其中有代表性的守护线程就是垃圾回收线程)         (2)、守护线程都是用在什么地方呢?                      每天00:00的时候系统自动备份数据,这个需要用到定时器,并且我们可以将定时器设置为守护线程,到了时间就会自动备份,但是当所有的用户线程退出的时候,守护线程就自动退出了,它没有必要再次进行备份了。         (3)、定时器的使用:间隔特定的时间,执行特定的程序。那么在Java中应该怎么实现定时器。                      一、可以采用sleep方法,让程序执行到此进行睡眠,等到睡眠一定时间之后,再次进行执行。(这种定时器较远老,比较low)                      二、Java的类库中已经写好了一个定时器,java.util.Timer,可以直接拿来用,但是这种方式也是比较古老,不建议使用。                      三、在实际开发中,使用较多的就是Spring提供的框架SpringTask,SpringTask小巧轻便,只需要简单的配置便可以使用,也可以使用Quartz框架,Quartz与SpringTask有各自的优缺点,使用哪个的话,就因人而异了。

    12、关于线程的调度?

            常见的线程调度模型有什么?         (1)、抢占式调度模型:                      哪个线程的优先级高,哪个线程抢到的CPU时间片多一些,Java采用的就是抢占式调度模型         (2)、均分式调度模型:                      平均分配CPU时间片,每个线程的CPU时间片相等,有一些编程语言,就是采用均分式调度模型。

            Java中提供了哪些方法和线程调度有关系?         实例方法:         void setPriroiry(int newPriority); //设置线程的优先级         int getPriroiry(); //获取线程的优先级         void join(); //合并线程

    class MyThread1 { public void doSome () { MyThread2 myThread2 = new MyThread2(); myThread2.join();//当前线程进入阻塞,myThread2线程执行,知道myThread2线程执行完毕,当前线程才可以继续执行。 } } class MyThread2 { }

            注意:线程的最低优先级是1、最高优先级是10、默认优先级是5、线程的优先级越高,获取CPU的时间片就会更多。

            静态方法:         static void yield(); //让位方法,暂停当前正在执行的线程,并执行其他线程         注意:该方法不是阻塞方法,只是让当前正在运行的线程停止,就是说让当前线程从“运行状态”重新回到“就绪状态”,回到就绪状态之后还有可能继续抢到CPU时间片进行执行。

    Processed: 0.008, SQL: 9