Java多线程编程(一)

线程的概念

进程时程序一次动态执行的过程,它对应着从代码加载,执行到执行完毕的一个完整过程。一个进程可以含有一个或多个线程,每个线程都有一个唯一的标识符。一个线程不能独立的存在,它必须时进程的一部分。一个进程一直运行,直到所有的非守候线程都结束运行后才能结束。

进程空间大体分为数据区,代码区,栈区,堆区,多个进程的内部数据和状态都是完全独立的;而线程共享进程的数据区,代码区,堆区。只有栈区时独立的。所以线程切换比进程切换代价小。

多线程能满足程序员编写非常有效率的程序来达到充分利用CPU的目的,因为CPU的空闲时间能够保持在最低限度。

线程的状态和生命周期

每个Java程序都有一个缺省的主线程。要想实线多线程,必须在主线程中创建新的线程对象。

一个线程完整的生命周期通常要经历5个状态:
创建状态(Born)
就绪状态(Ready)
运行状态(Running)
阻塞状态(Blocked Waiting Sleeping)
死亡状态(Dead)

Born

Java语言使用Thread类及其子类的对象来表示线程。
创建线程

Thread myThread = new Thread();

Ready

也叫可运行状态(Runnable)。新建的线程通过调用start()方法就处于就绪状态。
轮到Ready状态的线程来使用CPU时,就可以脱离创建它的主线程独立开始自己的生命周期了。
另外,原来处于阻塞状态的线程被解除阻塞状态的线程被解除阻塞后,也将进入就绪状态。

Thread myThread =  new Thread();
myThread.start();

Running

当就绪状态的线程被调度并获得处理器资源时便进入运行状态。每一个Thread类及其子类的对象都有一个重要的run()方法。当线程对象被调度执行时,它将自动调用此线程对象的run()方法。
运行中的线程,调用yield()方法可以自动放弃cpu而进入就绪状态。

Blocked Waiting Sleeping

一个正在运行的线程在某些特殊情况下,例如被人为挂起或者需要执行费时的输入输出操作时,将让出CPU并暂时中止自己的执行,进入阻塞状态。
阻塞时该进程不能进入排队队列。只有当引起阻塞的原因被消除时,线程才可以转入就绪状态,重新进入线程队列中排队等待CPU资源,以便从原来中止处开始继续运行。

Dead

执行完run()方法的最后一个语句并退出。

流程图
这里写图片描述

线程的优先级和线程调度策略

线程的优先级

每个线程都有一个优先级(priority) 数值在1-10之间。默认是5。
设置线程的优先级用Thread对象的方法setPriority(int priority)
用方法getPriority()获得线程的优先级

线程调度策略

当前线程执行过程中有较高优先级的线程进入就绪状态,则高优先级的线程立即被调度执行。
当调用yield()方法时,如果其他处于就绪状态的线程的优先级都比当前线程低,则yield()操作将被忽略。

线程的创建和执行

两个重要操作:
①定义用户线程的操作,即实现线程的run()方法的方法体
构造Thread类对象,实现线程的建立和运行控制

通过实现Runnable接口创建线程

Runnable接口介绍
Runnable接口只有一个方法run(),所有实现Runnable接口的类必须实现这个方法。
创建实现Runnable接口的类,在此类中实现Runnable接口中的run()方法,创建此类的对象,并将此对象作为参数传递给Thread类的构造方法,构造Thread类的构造方法,构造Thread对象并启动。

Thread(Runnable threadOb,String threadName);

这里threadOb是一个实现Runnable接口的类的实例,并且threadName指定新线程的名字。
新线程创建后调用start()方法使其Ready。

Demo

class NewThread implements Runnable {
    Thread t;
    NewThread() {
        //创建第二个新线程
        t = new Thread(this,"Demo Thread");
        System.out.println("Child Thread: "+t);
        t.start();
    }
    public void run() {
        try {
            for(int i = 5 ; i > 0 ; i --) {
                System.out.println("Child Thread: "+i);
                Thread.sleep(50);
            }
        }
        catch(InterruptedException e) {
            System.out.println("Child interrupted.");
        }
        System.out.println("Exiting child thread");
    }
}
public class ThreadDemo {
    public static void main(String []args) {
        new NewThread();//创建新的线程
        try {
            for(int i = 5 ; i > 0 ; i --) {
                System.out.println("Main Thread: "+i);
                Thread.sleep(100);
            }
        }
        catch(InterruptedException e) {
            System.out.println("Main thread interrupted.");
        }
        System.out.println("Main thread exiting.");
    }
}

结果
Child Thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread
Main Thread: 2
Main Thread: 1
Main thread exiting.

通过继承Thread类创建线程

Thread类
Thread类封装了一个线程需要拥有的属性和方法。Thread类实现了Runnable接口中的run方法,但方法体为空。
Thread类的常用方法

static Thread currentThread() //返回当前正在运行的线程的引用
static void yield() //当前线程进入Ready状态
static sleep(int millsecond) //设置休眠时间 sleep要抛出异常,必须捕获
void start() //启动线程,进入Ready状态
void run() //由线程调度器调用,当从run()返回时,该进程运行结束
final void setName(String name) //设置线程的名字
final String getName() //获取线程名字
interrupt() //中断线程对象所处的状态,进入Ready状态。抛出InterruptedException异常
final boolean isAlive() //判断线程是否被启动
void join() //使当前线程暂停运行,等调用join方法的线程运行结束,当前线程才继续运行。

创建用户定制的Thread类的子类,并在子类中重新定义自己的run()方法,这个run()方法中包含了用户线程的操作。这样在用户程序需要建立自己的线程时,只需要创建一个已经定义好的Thread子类的实例就可以了。

使用Thread类来创建线程Demo

//DisplayMessage.java
//通过实现Runnable接口创建线程
public class DisplayMessage implements Runnable {
    private String message;
    public DisplayMessage(String message) {
        this.message = message;
    }
    public void run() {
        while(true) System.out.println(message);
    }
}
//GuessANumber.java
//通过继承Thread类创建线程
public class GuessANumber extends Thread {
    private int number;
    public GuessANumber(int number) {
        this.number = number;
    }
    public void run() {
        int counter = 0;
        int guess = 0;
        do {
            guess = (int) (Math.random()*100+1);
            System.out.println(this.getName() + " guesses "+guess);
            counter ++;
        }while(guess != number);
        System.out.println("** Correct! "+this.getName() ++ " in "+counter + " guesses.**");
    }
}
//ThreadClassDemo.java
public class ThreadClassDemo {
    public static void main(String []args) {
        Runnable hello new DisplayMessage("Hello");
        Thread thread1 = new Thread(hello);
        thread1.setDaemon(true);
        thread1.setName("hello");
        System.out.println("Starting hello thread");
        thread1.start();

        Runnable bye = new DisplayMessage("Goodbye");
        Thread thread2 = new Thread(hello);
        thread2.setPriority(Thread.MIN_PRIORITY);
        thread2.setDaemon(true);
        System.out.println("Starting goodbye thread...");
        thread2.start();

        System.out.println("Starting thread3...");
        Thread thread3 = new GuessANumber(27);
        thread3.start();
        try {
            thread3.join();
        }
        catch(InterruptedException e) {
            System.out.println("Thread interrupted.");
        }
        System.out.println("Starting thread4...");
        Thread thread4 = new GuessANumber(75);
        thread4.start();
        System.out.println("main() is ending...");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值