Java线程简介

来源:互联网 发布:puppet doll淘宝 编辑:程序博客网 时间:2024/06/08 06:52

一 线程的定义

线程,是程序执行流的最小单元,线程是进程中的一个实体是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。

一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。


二 线程的调度

进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。

机制:把时间划分为许多时间片然后轮流运行 

如:计算机把1s以每5ms为一个时间片,每个线程运行5ms后把cpu交给下一个线程,让下一个线程运行。因为切换时间非常快感觉线程是在同时运行。

当运行Thread.sleep(1000),接下来的1000ms将放弃对cpu的使用权。


三 与进程的对比

进程是资源分配的基本单位。所有与该进程有关的资源,都被记录在进程控制块PCB中。以表示该进程拥有这些资源或正在使用它们。

另外,进程也是抢占处理机的调度单位,它拥有一个完整的虚拟地址空间。当进程发生调度时,不同的进程拥有不同的虚拟地址空间,而同一进程内的不同线程共享同一地址空间。
与进程相对应,线程与资源分配无关,它属于某一个进程,并与进程内的其他线程一起共享进程的资源。
线程与进程的区别可以归纳为以下4点:
1)地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
2)通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
3)调度和切换:线程上下文切换比进程上下文切换要快得多。
4)在多线程OS中,进程不是一个可执行的实体。

四 线程的创建

(1)通过扩展Thread类来创建多线程

新建一个类extends Thread->重写run()->创建对象->调用start()

(2)通过实现Runnable接口来创建多线程

implements Runnable()->重写run()->创建对象

例:

public class MutliThreadDemo2 {    public static void main(String [] args){        MutliThread m1=new MutliThread("Window 1");        MutliThread m2=new MutliThread("Window 2");        MutliThread m3=new MutliThread("Window 3");        Thread t1=new Thread(m1);        Thread t2=new Thread(m2);        Thread t3=new Thread(m3);        t1.start();        t2.start();        t3.start();    }}class MutliThread implements Runnable{    private int ticket=100;//每个线程都拥有100张票    private String name;    MutliThread(String name){        this.name=name;    }    public void run(){        while(ticket>0){            System.out.println(ticket--+" is saled by "+name);        }    }}
(3) 匿名内部类:直接创建Thread类对象,然后重写run()

public class ThreadDemo01 {    public static void main(String[] args) {        /*         * 第一种方式:         * 1.继承Thread类         * 2.重写run方法         * 3.将要执行的代码写在run方法中         */        new Thread() {            public void run() {                for (int i = 0; i < 10; i++) {                    System.out.println("aaaaaaaaa");                }            }        }.start();//开启线程    }}


        /*         * 第二种方式:         * 1.将Runnable的子类对象传递给Thread的构造方法         * 2.重写run方法         * 3.将执行的代码写在run方法中,最后我们开启线程         */        new Thread(new Runnable() {            public void run() {                for (int i = 0; i < 10; i++) {                    System.out.println("bbbbbbbbb");                }            }        }).start();//开启线程



五  线程的同步

详细了解:synchronized的四种用法

线程的同步是Java多线程编程的难点,需要考虑资源竞争、同步等。对于同步,在具体的Java代码中需要完成以下两个操作:把竞争访问的资源标识为private;同步哪些修改变量的代码,使用synchronized关键字同步方法或代码。当然这不是唯一控制并发安全的途径。synchronized关键字使用说明synchronized只能标记非抽象的方法,不能标识成员变量显然银行账户User对象是个竞争资源,而多个并发操作的是账户方法oper(int x),当然应该在此方法上加上同步,并将账户的余额设为私有变量,禁止直接访问。

工作原理
线程是进程中的实体,一个进程可以拥有多个线程,一个线程必须有一个父进程。线程不拥有系统资源,只有运行必须的一些数据结构;它与父进程的其它线程共享该进程所拥有的全部资源。线程可以创建和撤消线程,从而实现程序的并发执行。一般,线程具有就绪、阻塞和运行三种基本状态。
进程可以支持多个线程,它们看似同时执行,但互相之间并不同步。一个进程中的多个线程共享相同的内存地址空间,这就意味着它们可以访问相同的变量对象,而且它们从同一堆中分配对象。尽管这让线程之间共享信息变得更容易,但您必须小心,确保它们不会妨碍同一进程里的其它线程。


六 线程状态的变化

详细点击:线程的几种状态变化

(1)创建线程

当创建一个新的进程时,也创建一个新的线程,进程中的线程可以在同一进程中创建新的线程中创建新的线程。

(2)终止线程

可以正常终止自己,也可能某个线程执行错误,由其它线程强行终止。终止线程操作主要负责释放线程占有的寄存器和栈

(3)阻塞线程

当线程等待每个事件无法运行时,停止其运行。

(4)唤醒线程

当阻塞线程的事件发生,将被阻塞的线程状态置为就绪态,将其挂到就绪队列。进程仍然具有与执行相关的状态。例如,所谓进程处于“执行”状态,实际上是指该进程中的某线程正在执行。对进程施加的与进程状态有关的操作,也对其线程起作用。例如,把某个进程挂起时,该进程中的所有线程也都被挂起,激活也是同样。

原创粉丝点击