首页 > 代码库 > Java线程浅学习

Java线程浅学习



线程概述

线程是程序运行的基本执行单位,当操作系统执行一个程序时,会创建一个进程,而这个进程至少创建一个线程(主线程)作为这个程序的入口点。所以,在操作系统中运行的程序都至少有一个主线程。

进程和线程是现代操作系统必不可少的运行模型,在操作系统中可以有多个进程,这些进程包括系统进程(系统内部创建的进程)和用户进程(用户程序创建的进程),一个进程可以有多个线程。进程之间不存在内存共享,就是说,系统中的进程都是在各自的内存空间中运行的。但是一个进程中的线程可以共享系统分配给这个进程的内存空间。

线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,叫线程栈。是在建立线程时系统分配的,主要是保护线程内部所使用的数据。

创建线程的方法

        Java中创建线程的方法有两种:使用Thread类和使用Runnable接口。

  1. 使用thread类创建

    如下所示:

    NewThth=new NewTh();

    NewTh th1=new NewTh();

    Thread td=new Thread(th);

               Threadtd1=new Thread(th1);

    td.start();

        td1.start();

    这样就启动了线程。

    一个普通的Java类只要继承了thread类,就可以成为一个线程类,如下面的代码:

    packagecom.cn.test;

    //线程就是为了更好地利用CPU,提高程序运行速率的!

    publicclass MyThread extends Thread{

    private int i ;

    public void run(){

               for (int i = 0;i<100;i++){

                        System.out.println(Thread.currentThread().getName()+""+i);

               }

              

    }

    public static void main(String[] args) {

               new MyThread().run();

               //run()方法当作普通方法的方式调用,程序还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码。

               new MyThread().start();

               //start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。

               new MyThread().start();

    }

    }

  2. 使用Runnable接口

    使用接口Runnable创建一个线程时,需要调用该对象的run方法。

    如代码:

    packagecom.cn.test;

    //线程就是为了更好地利用CPU,提高程序运行速率的!

    publicclass MyThread1 {

    public static void main(String[] args) {

               NewTh th=new NewTh();

               NewTh th1=new NewTh();

               Thread td=new Thread(th);

               Thread td1=new Thread(th1);

               th.run();

               th1.run();

               //th.start();  th对象没有start()方法,在这里run()方法相当于方法的调用,

              

               td.start();

        td1.start();

               td.run();

               td1.run();

    }

    }

    classNewTh implements Runnable{

    int i=0;

    @Override

    public void run() {

               // TODO Auto-generated method stub

               for(int i =0 ;i<20;i++){

                        System.out.println(Thread.currentThread().getName()+"" +i);

                       

               }

               System.out.println("金丝燕,未来无极限");

    }

    }

  3. 线程的启动

    通过以上的例子,可以发现继承了Thread类的线程启动执行start()方法和run()方法,而实现Runnable接口的只能执行run()方法,而这两个有什么区别那?

    Start

    start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体执行完毕而直接继续执行下面的代码。通过Thread类的start()方法来启动一个线程,这时线程就会处于可运行状态,但并没有运行,一旦得到CPU时间片段就开始执行run方法,这时run()称为线程体,它包含了这个线程要执行的内容,Run方法执行结束,此线程终止。

    Run

    run()方法只是类的一个普通方法,如果调用run方法,那么只用等run方法执行完毕才能执行下面的代码。

线程的状态

线程中除了有startrun方法来操作线程的状态,还有一些其他的方法来控制。

  1. 睡眠线程

    sleep(long millis)方法

    让线程停止一段时间,在sleep时间间隔期满后,线程不一定立即恢复执行,因为在这一时刻,其他线程正在运行而没有被调度为放弃执行,除非恢复过来的线程具有更高的优先级,或者正在运行的线程因为其他原因而被阻塞。sleep(long millis,int nanos)方法,millis - 以毫秒为单位的休眠时间,nanos-要休眠的另外 0-999999 纳秒。

    如代码:public classMyThread extends Thread {

        public void run() {

            for (int i = 0; i < 100; i++) {

                if ((i) % 10 == 0) {

                   System.out.println("-------" + i);

                }

                System.out.print(i);

                try {

                    Thread.sleep(1000);

                    System.out.println("   线程睡眠1秒!");

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        }

        public static void main(String[] args) {

            new MyThread().start();

        }

    }

    wait()方法

    让线程等待一段时间,或者是在其他线程调用此对象的 notify()方法或 notifyAll() 方法前等待

    等待对象的同步锁,需要获得该对象的同步锁才可以调用这个方法,否则编译可以通过,但运行时会收到一个异常:IllegalMonitorStateException。调用任意对象的 wait() 方法导致该线程阻塞,该线程不可继续执行,并且该对象上的锁被释放。

notify()方法

唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。

调用任意对象的notify()方法则导致因调用该对象的wait()方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。

notifyAll()

唤醒所有等待的线程,注意唤醒的是notify之前wait的线程,对于notify之后的wait线程是没有效果的。

resume()方法和suspend()

suspend()方法使得线程进入阻塞状态,并且不会自动恢复,必须调用其对应的resume()方法才能使得线程重新进入可执行状态。

resume方法和suspend方法在一起使用,具有固有的死锁倾向。如果目标线程挂起时在保护关键系统资源的监视器上保持有锁,则在目标线程重新开始以前任何线程都不能访问该资源,如果重新开始目标线程的线程想在调用resume之前锁定该监视器,则会发生死锁,这类死锁通常会证明自己是“冻结”的进程。

stop()

stop()方法是不安全的,该方法已经过时,在调用Thread.stop方法的时候,会即刻抛出ThreadDeath异常,同时会释放该线程的所有的锁。调用stop方法会产生不完整的残废数据,而多线程编程最最基础的就是保证数据的完整性,所以不建议使用stop方法。

interrupt()

请移步http://blog.csdn.net/cxy782255346/article/details/38472851

isAlive()

用于测试线程是否处于活动状态,如果线程已经启动且尚未终止,则为活动状态。如果该线程处于活动状态则返回TRUE,否则返回FALSE

join()

join()用于停止当前线程而运行别的线程。换句话说就是,join()方法可以把两个交替执行的线程合并为顺序执行的线程,比如在线程B中调用了线程A中的join()方法,那么就会等到线程A执行完之后,B线程才会继续执行。


 

 

 

 

 

Java线程浅学习