黑马程序员--Java编程之多线程

来源:互联网 发布:决战武林神兵进阶数据 编辑:程序博客网 时间:2024/04/25 00:55

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

一.线程与进程

一.进程:

1.什么是进程:它是”操作系统”中的概念;对于操作系统来说,每个单独运行的”程序”就是一个”进程”;
2.什么是多进程:是指操作系统可以同时维护多个应用程序的同时运行;统一分配资源;
3.多进程的意义:
1).充分的利用系统资源;
2).可以提高用户的体验度;使用户有非常好的使用体验;

二.线程:

1.什么是线程:线程是指,由一个”进程”中启动的一个可以独立运行的代码块;它是某个进程的一部分;
线程可以跟”主进程”一同抢夺系统资源;一个主进程可以开出任意多的线程;
2.什么是多线程:是指一个程序可以开出多个”线程”同时执行;
3.多线程的意义:
1).充分的利用系统资源;
2).对于一个软件来说,就好像同时在有多个功能在一起运行;

三.多线程程序和单线程程序:

1.单线程程序:只有一条执行路径;后面的代码必须等待前面的代码执行完毕才能获得执行;
2.多线程程序:可以有多条执行路径,就好像多个功能在同时运行;

四.并行和并发:

1.并行:是指两个线程在”某个时间段内”,同时在运行;
2.并发:是指多个线程在”某个时间点上”,同时访问同一资源;

二.实现线程的方式

方式一

1.自定义线程类,继承自Thread;
2.重写run()方法;
3.启动线程:
1).实例化自定义线程类对象;
2).调用线程对象的start()方法启动线程;
注意:
1.对于同一个Thread(包括子类)对象,不能多次调用start()方法;
2.对于同一个Thread(包括子类)类,可以产生多个对象,每个对象都可以单独start(),成为一个独立的线程;

方式二:

1.自定义类,实现:Runnable接口;
2.重写run()方法;
3.启动线程:
1).实例化自定义类对象;
2).实例化一个Thread对象,并将自定义对象传递给Thread的构造方法;
3).调用Thread对象的start()方法启动线程;

三.线程中的方法

1.获取和设置线程对象名称

每个线程,都有一个”线程名称”;默认名称:Thread-(索引),那么怎么获取和设置线程名称呢?
1).getName():获取线程名;
2).setName(String n):设置线程名称;
我们可以在任何的线程中使用Thread.currentThread()获取当前正在运行的线程对象;并调用getName()即可以获取此线程对象的线程名称;

2.线程的优先级

1).Java中线程优先级的范围:1–10(从低到高);
2).设置优先级:
getPriority():获取优先级;
setPriority():设置优先级;(范围一定从1–10)
3).注意:我们不要依赖于”线程优先级”的技术,期望某个线程先执行完毕;因为它不保证线程优先级高的就一定先执行完毕,这个要由”操作系统”来统一调度;”高优先级”的线程只代表:具有更多的机会被操作系统执行而已,并不代表一定会先执行完毕;另外,如果线程中所做的事情比较简单,线程”优先级”的效果会不明显;

3.线程休眠

public static void sleep(long millis):

4.线程加入

public final void join():调用此方法的线程,将会保证先执行完毕,其它线程才可以被执行;

5.线程礼让

public static void yield():使调用的线程退回到”就绪”状态,等待操作系统再次分配,很有可能被操作系统再次分配到执行权;

6.线程守护

public final void setDaemon(boolean on):如果on为true,则表示为:守护线程
1.非守护线程:当主线程执行完毕时,程序不会立即结束,会等待所有开出的线程执行完毕,主进程才结束;
2.守护线程:当主线程结束时,开出的”守护线程”也会随着终止(但是不会立即终止,会有个小缓冲)

7.中断线程

public final void stop():不建议使用
public void interrupt():前提条件:线程的内部,一定要处于以下三种阻塞状态时:
1.Object–>wait()
2.Thread–>sleep()
3.Thread–>yield()
当在外部调用线程的interrupt()方法时,将促使上述方法抛出异常从而达到中断线程的效果;

四.多线程程序–卖票案例

public class Demo {    public static void main(String[] args) {        // 1.创建一个票池对象        TicketPool tp = new TicketPool();        // 2.创建三个线程对象,模拟三个窗口售票        MyThread t1 = new MyThread(tp);        MyThread t2 = new MyThread(tp);        MyThread t3 = new MyThread(tp);        //给线程起名字        t1.setName("窗口1");        t2.setName("窗口2");        t3.setName("窗口3");        //启动线程        t1.start();        t2.start();        t3.start();    }}class MyThread extends Thread{    private TicketPool tp = null;    private int count = 0;    public MyThread(TicketPool p){        this.tp = p;    }    @Override    public void run() {        while(true){            int n = this.tp.getTicket();            if(n == 0){//没票了                break;            }else{                count++;                System.out.println(this.getName() + " 抢到票:" + n);            }        }        System.out.println(this.getName() + " 停止抢票了! 共抢到:" + count + "张票");    }}class TicketPool {    private int tickets = 100;    //获取一张票    public int getTicket(){//窗口2        //同步代码块        synchronized (this) {//窗口1(锁)            if(this.tickets > 0 ){                try {                    Thread.sleep(1);                } catch (InterruptedException e) {                    e.printStackTrace();                }                return tickets--;            }else{                return 0;            }        }    }}
0 0