码迷,mamicode.com
首页 > 编程语言 > 详细

关于多线程的入门_进阶总结

时间:2016-11-15 23:19:33      阅读:322      评论:0      收藏:0      [点我收藏+]

标签:无法   cep   zed   images   idt   1.3   center   新建   理解   

多线程

1.概述

进程:应用程序在内存中运行的空间;

线程:进程中的一个执行单元,一个进程至少有一个线程.多个执行单元就是多线程了(进程可以理解为是一个QQ程序,QQ运行本身就是一个线程(main),你可以在QQ上做好多事情,每个事情就相当于一个线程);

 线程的存在解决什么问题?
    多部分代码同时执行的问题。
    传统的单个主线程从头执行到尾的运行安排,当遇到较多的操作次数时,效率偏低
 多线程的弊端:
     开启过多会降低效率,多线程的原理其实是多个执行单元执行一个程序,CPU高速在多个线程之间进行切换,
      当线程个数过多时,CPU切换一个循环的时间过长,相应的降低了程序运行的效率
 多线程的特性:

      随机性,因为CPU的快速切换造成的。

其他总结:线程有并发性

技术分享

2,创建线程

            1,通过原来的主线程的执行和需求做对比。
            2,需求:在主线程中执行到部分代码多次无法继续执行,如何实现让下面的代码和主线程同时执行。
            3,创建方式,通过查api。Thread类。
                继承Thread类。
                3.1 定义一个类继承Thread。
                3.2 重写run方法。
                3.3 创建子类对象,就是创建线程对象。
                3.4 调用start方法,开启线程并让线程执行,同时还会告诉jvm去调用run方法。
                目的让主线程和自定义线程同时执行。
                class ThreadDemo
                {
                    public static void main(String[] args)
                    {
                        Ticket t = new Ticket(100);
                        Ticket t1 = new Ticket(10);

                        t.start;
                        t1.run();
                    }
                }
                class Ticket extends Thread
                {
                    private int tickets;
                    Ticket( int tickets ){
                        this.tickets = tickets;
                    }
                    public void run(){
                        if ( ticket>0 )
                        {
                            System.out.println(Thread.currentThread().getName()+tickets--);
                        }
                    }
                }
            5,体会,调用run和调用start的区别?
                调用run方法仅仅是主线程执行run方法中的代码;调用start方法是开启线程,让新建的线程与主线程同时执行

其他总结:注意在这个程序中,run()方法是中没有循环的;没有创建线程就不能执行;一个线程只有调用了start()方法才能开始线程,

3,创建线程方式一的原理         

           1,为什么要继承Thread,
                因为Thread类描述了线程的任务存在的位置:run方法。
            2,为什么要覆盖run方法。
                为了定义线程需要运行的任务代码。
            3,为什么调用start方法。
                为了开启线程,并运行子类的run方法的任务代码。
            4,创建线程的目的是什么?
                为了执行线程任务,而是任务都定义在run方法中。
                run方法结束了,线程任务就是结束了,线程也就是结束了。
            5,线程任务:每一个线程都有自己执行的代码,主线程的代码都定义在主函数中,自定义线程的代码都定义在run方法中。

4,多线程的运行原理
            1,疑问,如果多部分代码同时执行,那么在栈内存方法执行是怎么完成的呢?
                其实是,每一个线程在栈内存中都有自己的栈内存空间,在自己的栈空间中
                进行压栈和弹栈。
            2,主线程结束,程序就结束吗?
                主线程结束,如果其他线程还在执行,进程是不会结束了,当所有的线程都结束了,进程才会结束。
            3,画出多线程的运行内存图。

技术分享5, 异常在多线程中的特点
            throw异常是可以结束功能。
            如果功能是线程的任务,那么功能结束就代表着线程结束。
            而且异常信息中会体现出该异常在哪个线程上发生。
            Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: 4
                at Demo.run(ThreadDemo.java:68)


    ------------------------
6,创建线程的方式二,实现Runnable接口
            1,通过查阅api得到第二种方式。
            2,不明确原理的情况下,先应用。
            3,方式二步骤:
                3.1,定义类实现Runnable接口:
                3.2,覆盖接口中的run方法。
                3.3,创建Thread类的对象:
                3.4,将Runnable接口的子类对象作为参数传递给Thread类的构造函数。
                3.5,调用Thread类的start方法开启线程。
                到这里,你就应该可以使用方式二创建线程了。动手自己通过方式二完成线程的创建并运行。★★★★★
            4,方式二的原理:★★★
                4.1,定义类实现Runnable接口:避免了继承Thread类的单继承局限性。
                4.2,覆盖接口中的run方法。将线程任务代码定义到run方法中。
                4.3,创建Thread类的对象:只有创建Thread类的对象才可以创建线程。
                4.4,将Runnable接口的子类对象作为参数传递给Thread类的构造函数。
                    因为线程已被封装到Runnable接口的run方法中,而这个run方法所属于Runnable接口的子类对象,
                    所以将这个子类对象作为参数传递给Thread的构造函数,这样,线程对象创建时就可以明确要运行的线程的任务。
                4.5,调用Thread类的start方法开启线程。
            5,方式二和方式一的区别:【面试题】★★★★★
                5.1 第二种方式实现Runnable接口避免了单继承的局限性,所以较为常用。
                5.2 实现Runnable接口的方式,更加的符合面向对象,线程分为两部分,一部分线程对象,一部分线程任务。
                    继承Thread类:线程对象和线程任务耦合在一起。一旦创建Thread类的子类对象,既是线程对象,有又有线程任务。
                    实现runnable接口:将线程任务单独分离出来封装成对象,类型就是Runnable接口类型。
                    Runnable接口对线程对象和线程任务进行解耦。
           技术分享
    ------------------------
7,线程的状态
            1,线程运行是有多种状态的。
                1.1 创建  new Thread类或者其子类对象。
                1.2 运行 start().  具备者CPU的执行资格和CPU的执行权。
                1.3 冻结 释放了CPU的执行资格和CPU的执行权。比如执行到sleep(time)  wait() 导致线程冻结。
                1.4 临时阻塞状态: 具备者CPU的执行资格,不具备CPU的执行权。
                1.5 消亡:线程结束。run方法结束。
          
        技术分享
            
    ------------------------
8,多线程的安全问题

案例:售票的示例。
            1,通过案例让安全问题发生。
            2,安全问题产生的原因:
                2.1 线程任务中有共享的数据。
                2.2 线程任务中有多条操作共享数据的代码。
                当线程在操作共享数据时,其他线程参与了运算导致了数据的错误(安全问题)
            3,安全问题的解决思路:
                保证在线程执行共享数据代码时,其他线程无法参与运算。
            4,安全问题的解决代码体现:
                同步代码块。synchronized(obj){需要被同步的代码}  【举例:火车上的卫生间】
            5,同步的好处:
                解决了安全问题。
            6,同步的弊端:
                降低了程序的性能。
            7,同步的前提:
                必须保证多个线程在同步中使用的是同一个锁。
                解决了什么问题?
                当多线程安全问题发生时,加入了同步后,
                问题依旧,就要通过这个同步的前提来判断同步是否写正确。

其他总结:同步里面的对象相当于火车上卫生间的锁,火车上就你自己一个人,你去卫生间不用锁,3号卫生间的锁和4号卫生间的锁是没有关系的.因此多个线程要用同一个锁.

技术分享

    ------------------------

//写出下面代码执行的结果(此题需写出分析过程)

class MyThread extends Thread{
    public void run(){
        try {
            Thread.currentThread().sleep(3000);
        } catch (InterruptedException e) {
        }
        System.out.println("MyThread running");
    }
}

public class ThreadTest{
    public static void main(String argv[]) {
        MyThread t = new MyThread();
        t.run();
        t.start();
        System.out.println("Thread Test");
      }
}
执行结果:
    MyThread running
    Thread Test
    MyThread running
过程分析:
    1,MyThread t = new MyThread();
        创建线程对象,但并未开启。
    2,t.run();
        是主线程执行t对象的run方法。
        在run方法中,主线程执行到sleep(3000);主线程就处于冻结状态,
        3秒后,主线程恢复到运行状态,就打印了"MyThread running"。
    3,t.start();
        主线程执行该句,开启了一个新的线程Thread-0。
        这时程序中有两个线程,执行出现了两种情况:
            情况一:主线程执行完t.start()方法后,继续执行打印语句,输出"Thread Test"。
                    然后新线程Thread-0执行run方法,并sleep(3000)3秒,3秒后,执行"MyThread running"
            情况二:主线程执行完t.start()方法后,开启了一个新线程Thread-0,
                    该新线程Thread-0就开始执行,调用run方法,sleep(3000)3秒,这时主线程开始执行,
                    打印了"Thread Test",主线程结束,3秒后,新线程Thread-0打印"MyThread running"。

由于个人水平有限,有什么问题可以在下面评论.QQ:330141830.微信:15637979392.上面内容有视频讲解,可以找我要.

欢迎扫下面二微码给我打赏.( ̄︶ ̄)


         技术分享        

                          微信                 

        技术分享

                         支付宝

 

关于多线程的入门_进阶总结

标签:无法   cep   zed   images   idt   1.3   center   新建   理解   

原文地址:http://www.cnblogs.com/liu-wang/p/6067525.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!