day-13-对线程【Thread、线程创建】

来源:互联网 发布:sql declare怎么运行 编辑:程序博客网 时间:2024/05/18 02:34

1.线程

一个线程就是一个正在运行的程序;就是程序执行的线路(路径);

如果程序中同时有两个或两个以上的程序在执行,这个程序叫做多线程程序;

进程:是应用程序的载体,当软件一运行起来的时候,系统就会给这个软件创建一个新的进程。一个应用程序(软件)对应一个进程;

一个进程里面可以包含多个线程,一个线程里面只能包含一个进程;

好处:

提高软件的运行效率(性能);

1.1 多线程程序运行的原理

在同一时刻只能有一个线程正在运行CPU。CPU资源的调度方式:    第一种:分时调度        操作系统会给多个线程平均分配CPU的时间;    第二种:抢占式调度        根据线程的优先级分配CPU资源,优先级高的线程最先得到CPU资源;

2.开发多线程程序

运行main方法的线程叫做主线程;

开发多线程程序有两种方式:

1.继承Thread类    构造方法:        Thread():创建线程对象,线程名字有默认的;        Thread(String name):使用执行的名字创建线程对象;    成员方法:        String getName():得到线程的名字;        void run():运行现成的逻辑代码的;        void start():开启线程,只是开启线程处于就绪状态,并不是运行线程,当操作系统给它分配CPU资源后才能处于运行状态调用run方法;    格式:        修饰符 class 类名 extends Thread{                重写run方法(){                    子线程执行的代码;            }        }    使用子线程步骤:        1.定义子线程类,继承父类Thread类,重写run方法;        2.创建子线程对象;        3.调用对象的stert()方法;    得到线程的名字:        Thread.currentThread():得到当前线程对象;        String getName():得到线程的名字;        一行代码搞定:            Thread.currentThread().getName():得到线程的名字;2.实现Runnable接口    步骤:        1.定义一个类,实现Runnable接口,重写run方法,这个中写子线程要执行的代码;          2.创建子任务对象;        3.创建子线程对象:Thread t=new Thread(子任务对象);        4.调用子线程对象的start方法;

两种方式的区别:

1.第一种方式把任务的代码与子线程的代码耦合带一起了,第二种方式 把任务的代码和子线程的代码分开了,解耦性强;2.第一种方式继承了Thread类,具有继承的局限性,扩展性不强,第二种实现了接口,还可以继承其他父类,扩展性强;

3.非线程安全的问题

三子线程共卖100张票,出现了卖重复的票,第0张票,副票;原因:    多个线程在改变一个共享的数据时, 出现了某一个线程不想要的结果.解决办法:    保证修改共享数据的代码在同一时刻只能被一个线程执行,保证线程是同步的;常用的方式有两种:    1.使用同步代码块        使用关键字syncronized修饰一个代码块:修改共享数据的代码;        格式:            syncronized(锁对象){                    修改共享数据的代码;                }        同步:代码从上往下一行一行的执行;        异步:多个线程同时执行;        锁对象:            用来锁住同步代码块的,只有获得这个锁对象的线程才能执行同步代码块,线程执行完同步代码块后,释放锁对象,然后其他线程才能得到锁对象;

示例代码:

public class TicketRunnable implements Runnable {// 共享的100张票,可以让三个窗口(子线程)卖这100张票        int ticketNumber = 100;    // 作为锁对象    Object obj = new Object();            @Override        public void run() {            while (true) {    // 只有获得obj对象的线程才能执行下面的代码.    // synchronized(obj){    // 可以使用this作为锁对象,因为三个线程使用的是同一个TicketRunnable对象,this就是TicketRunnable对象        synchronized (this) {            if (ticketNumber > 0) {    // 让当前线程睡眠50毫秒.模拟网络延迟的时间                try {                    Thread.sleep(50);                } catch (InterruptedException e) {                        e.printStackTrace();                }    System.out.println(Thread.currentThread().getName() + "正在卖第" + (ticketNumber--) + "张票");                }            }        }    }}2.使用同步方法    格式:    修饰符 syncronized 返回值类型 方法名(参数列表){                    修改共享数据的代码;                }

示例代码:

public class TicketRunnable implements Runnable {// 共享的100张票,可以让三个窗口(子线程)卖这100张票    int ticketNumber = 100;        // 作为锁对象    Object obj = new Object();            @Override    public  void run() {        while(true){                //调用同步方法            sell();        }    }    // 同步方法使用的锁对象默认是this    public synchronized void sell(){        if(ticketNumber > 0){    // 让当前线程睡眠50毫秒.模拟网络延迟的时间            try {                    Thread.sleep(50);            }catch (InterruptedException e) {                    e.printStackTrace();            }    System.out.println(Thread.currentThread().getName()+"正在卖第"+ (ticketNumber--) +"张票");            }        }    }3.lock锁接口    Lock lock = new  ReentrantLock();        // 获得锁对象        lock.lock();            同步代码块;        //释放锁对象        lock.unlock();        同一时刻只能有一个

4.线程状态

新建状态:创建了线程对象后; 就绪状态:调用start方法后;运行状态:调用run方法后;等待状态:锁对象正被其他线程使用,自己没有获得锁对象.休眠状态:自己获得了锁对象,但是调用了自己的sleep方法,自己处于休眠状态.结束(死亡)状态:run方法执行完毕后;
原创粉丝点击