您的位置:首页 > 编程语言 > Java开发

Java基础--线程

2018-03-26 15:29 155 查看
一、线程和进程的概念?
1.要想了解多线程,必须先了解线程,要想了解线程,必须先了解进程,因为线程是依赖进程而存在的。



2:什么是进程?
            通过任务管理器我们就看到了进程的存在
            而通过观察,我们发现只有运行的程序才会有进程
            进程:就是正在运行的程序
            进程是系统进行资源分配和调用的独立单位,每一个进程都有他自己的内存空间和系统资源。

3:多进程的意义呢?
     单进程的计算机只做一件事情,而我们现在的计算机都可以做多件事情
  举例:一边玩游戏(游戏进程),一边音乐(音乐进程)。
  也就是说现在的计算机都是支持多进程的,可以在一个时间段内执行多个任务。
  并且呢,可以提高CPU的使用率
  问题:
    一边游戏,一边听音乐是同时进行的吗?
    不是。因为单CPU在某个时间点上只能做一件事情
    而我们在玩游戏,或者听音乐的时候,是CPU在做程序间的高效切换让我们感觉是同时进行。
    
 4:什么是线程?
 在同一个进程内又可以执行多个任务,而这每一个任务我就可以看出是一个线程。
 线程:是程序的执行单元,执行路径,是程序使用CPU的最基本单位。
 单线程:如果程序只有一条执行路径。
 多线程:如果程序有多条执行路径

 5:多线程的意义?
 多线程的存在,不是提高程序的执行速度。其实是为了提高应用程序的使用率。
 程序的执行其实都是在抢CPU的资源,CPU的执行权。
 多个进程是在抢这个资源,而其中的某一个进程如果执行路径比较多,就会有更高几率抢到CPU的执行权。

 我们是不敢保证哪一个线程能够在哪个时刻抢到,所以线程的执行有随机性。
并行和并发的理解?
并行的概念是在某一个时间段内同时运行多个程序,
并发的概念是在某一个时间点上同时运行多个程序

 思考题:
 *    jvm虚拟机的启动是单线程还是多线程的?
 *       多线程的。
 *       原因是垃圾回收线程也要先启动,否则容易会出现内存溢出。

 *       现在的垃圾回收线程加上前面的主线程,最低启动两个线程,所以jvm的启动是多线程的。
6:什么是线程安全和线程非安全?
多个线程访问同一个资源,导致结果和期望值不同,我们就说它是 非线程安全的(线程不安全),反之我们就说它是 线程安全的。
在说start()和run()方法之前我们先说一下run()方法的作用
因为一个类中不是所有的代码都会被线程执行,所以为了区分我们将需要线程执行的代码用run()方法包含起来
所以就有如下所说的run()方法只是一个普通的方法来封装被线程执行的代码

7:面试题start()和run()的区别?
         *    run()和start()方法的区别?
         * run():仅仅是封装被执行的线程代码,直接调用是普通方法
         * start():首先启动了线程,然后再由JVM去调用该线程的run()方法。
         * MyThread my = new MyThread();
         * my.start();
         * my.start();
         * IllegalThreadStateException:非法的线程状态异常
         *
         * 因为相当于是my线程被调用了两次,而不是两个线程启动

        //正确的是创建两个线程对象
        MyThread my1 = new MyThread();
        MyThread my2 = new MyThread();
        my1.start();

        my2.start();

8:什么是守护线程?
在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)
用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守护线程的保姆:
只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。
Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是 GC (垃圾回收器),它就是一个很称职的守护者。
User和Daemon两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果 User Thread已经全部退出运行了,只剩下DaemonThread存在了,虚拟机也就退出了。 因为没有了被守护者,Daemon也就没有工作可做了,也就没有继续运行程序的必要了。
/*
 * 后台线程:
 * public final void setDaemon(boolean on):将该线程标记为守护线程或用户线程
 * 当正在运行的线程都是守护线程是,Java虚拟机退出,该方法必须在启动线程前调用
 */
public class ThreadDaemonDemo {
    public static void main(String[] args) {
        //创建线程对象
        ThreadDaemon td1 = new ThreadDaemon();
        ThreadDaemon td2 = new ThreadDaemon();
        
        td1.setName("张飞");
        td2.setName("关羽");
        
        td1.setDaemon(true);
        td2.setDaemon(true);
        
        td1.start();
        td2.start();
        
        Thread.currentThread().setName("刘备");
        for(int x = 0;x<5;x++){
            System.out.println(Thread.currentThread().getName()+":"+x);
        }
    }
}
9:什么是等待线程终止?
/*
 * public final void join():等待线程终止
 * 只有引入join()方法的线程执行完之后才能执行其他的线程。
 */
public class ThreadJoinDemo {
        public static void main(String[] args) {
            //创建线程对象
            ThreadJoin tj1 = new ThreadJoin();
            ThreadJoin tj2 = new ThreadJoin();
            ThreadJoin tj3 = new ThreadJoin();
            
            //设置线程名称
            tj1.setName("李渊");
            tj2.setName("李世民")
4000
;
            tj3.setName("李元霸");
            
            //启动线程
            tj1.start();
            try {
                tj1.join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            tj2.start();
            tj3.start();
        }

}
10:什么是线程的优先级?怎么去设置线程优先级?
/*
 * 我们的线程没有设置优先级,肯定有默认优先级。
 * 那么,默认优先级是多少呢?
 * 如何获取线程对象的优先级?
 *         public final int getPriority():返回线程对象的优先级
 * 如何设置线程对象的优先级呢?
 *      public final void setPriority(int newPriority()):更改线程的优先级
 *
 * 注意:
 *     线程默认优先级是5
 *     线程优先级的范围是:1-10;
 *     线程优先级高仅仅是线程获取的CPU时间片的几率高,但是要在此时比较多,或者多次运行的时候才能看到。
 *     
 * IllegalArguementException:非法参数异常
 * 抛出的异常表明向方法传递了一个不合法或不正确的参数    
 */
public class ThreadPriorityDemo {
    public static void main(String[] args) {
        ThreadPriority tp1 = new ThreadPriority();
        ThreadPriority tp2 = new ThreadPriority();
        ThreadPriority tp3 = new ThreadPriority();
        
        tp1.setName("东方不败");
        tp2.setName("岳不群");
        tp3.setName("林平之");
           
        //默认获取优先级
//        System.out.println(tp1.getPriority());
//        System.out.println(tp2.getPriority());
//        System.out.println(tp3.getPriority());

        //设置线程优先级
        tp1.setPriority(10);
        tp2.setPriority(1);
        
        //启动线程
        tp1.start();
        tp2.start();
        tp3.start();
    }
}

11、线程的生命周期?



线程的状态
1、新建状态(New):新创建了一个线程对象。
2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
  (一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
  (二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
  (三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期
12、wait()和sleep()的区别?
wait时会释放锁资源但sleep不会释放锁资源,wait通常和notify以及notifyAll结合使用,需要notify或者notifyAll对其进行唤醒,sleep通常在指定的时间内自动唤醒
13、实现线程安全的办法?
A:同步代码块
            synchronized(对象) {
                需要被同步的代码;
            }
            
            这里的锁对象可以是任意对象。
            
        B:同步方法
            把同步加在方法上。
            
            这里的锁对象是this
            
        C:静态同步方法
            把同步加在方法上。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: