JavaSE学习 第十六章 线程

来源:互联网 发布:myfax网络传真机 编辑:程序博客网 时间:2024/06/11 08:12

参考 :http://xiao1227372602.iteye.com/blog/1630840

进程与线程     http://t240178168.iteye.com/blog/1681750

 

JAVA线程池原理以及几种线程池类型介绍   http://t240178168.iteye.com/blog/1629433


 

进程通信    http://t240178168.iteye.com/blog/1749312

   

线程间实现同步互斥的方法    http://t240178168.iteye.com/blog/1749315

由生产者/消费者问题看JAVA多线程     http://yangyushuai.iteye.com/blog/1830034

java锁机制     http://yangyushuai.iteye.com/blog/1830036


java中HashMap在多线程环境下引起CPU100%的问题解决       http://shuaijie506.iteye.com/blog/1815213

进程间通信:Windows下进程间通信的手段       http://t240178168.iteye.com/blog/1749308


synchronized关键字、Callable以及线程池     http://t240178168.iteye.com/blog/1706707


1.什么是线程

线程是一个程序内部的顺序控制流。

线程和进程:

每个进程都有独立的代码和数据空间(进程上下文),进程切换的开销大。

线程: 轻量的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小。

多进程: 在操作系统中能同时运行多个任务(程序)

多线程:在同一应用程序中有多个顺序流同时执行

 

2.线程的概念模型

1. 虚拟的CPU,由java.lang.Thread类封装和虚拟;

2. CPU所执行的代码,传递给Thread类对象;

3. CPU所处理的数据,传递给Thread类对象。

1

 

Java的线程是通过java.lang.Thread类来实现的。

每个线程都是通过某个特定Thread对象所对应的,方法run( )来完成其操作的,方法run( )称为线程体。

 

3.创建线程的两种方式的比较

一. 使用Runnable接口创建线程:

可以将CPU(Tread 类)、代码和数据(Runnable接口 run 方法)分开,形成清晰的模型;线程体run()方法所在的类还可以从其他类继承一些有用的属性或方法;

并有利于保持程序风格的一致性。

 

public class TestTread1{    public static void main(String args[]) {        Runner1 r = new Runner1();        Thread t = new Thread(r);        t.start();    }}class Runner1 implements Runnable {    public void run() {        for(int i=0; i<30; i++) {            System.out.println("No. " + i);        }    }}

 

二. 直接继承Thread类创建线程:

Thread子类无法再从其他类继承,编写简单,run()方法的当前对象就是线程对象,可直接操纵。

 

public class TestTread2{    public static void main(String args[]){        Thread t = new Runner3();        t.start();    }}class Runner3 extends Thread {    public void run() {        for(int i=0; i<30; i++) {            System.out.println("No. " + i);        }    }}

 

4.多线程

Java 中 引 入 线 程 机 制 的 目 的 在 于 实 现 多 线 程 (Multi-Thread),多线程之间可以共享代码和数据。

public class TestTread3{    public static void main(String args[]) {        Runner2 r = new Runner2();        Thread t1 = new Thread(r);        Thread t2 = new Thread(r);        t1.start();        t2.start();    }}class Runner2 implements Runnable {    public void run() {        for(int i=0; i<10; i++) {            String s = Thread.currentThread().getName();            System.out.println(s + ": " + i);        }    }}

结果:

Thread-0: 0Thread-0: 1Thread-0: 2Thread-0: 3Thread-0: 4Thread-0: 5Thread-0: 6Thread-0: 7Thread-0: 8Thread-0: 9Thread-1: 0Thread-1: 1Thread-1: 2Thread-1: 3Thread-1: 4Thread-1: 5Thread-1: 6Thread-1: 7Thread-1: 8Thread-1: 9

 

2

 

5.后台线程

相关基本概念:

后台处理(Background Processing):让某些程序的运行让步给其他的优先级高的程序

后台线程(Background Thread / Daemon Thread):以后台的方式(往往是服务线程)运行的线程,例如定时器线程

用户线程(User Thread):完成用户指定的任务的线程

主线程(Main Thread):它就是一种主线程

子线程(Sub Thread):在线程中创建的线程就是子线程

Thread类提供的相关方法:

public final boolean isDaemon():判断某个线程是不是一个后台线程

public final void setDaemon(Boolean on):设置某个线程为一个后台线程

举例:

package v512.chap16;public class TestDaemonThread {        public static void main(String args[]){        Thread t1 = new MyRunner(10);        t1.setName("用户线程t1");        t1.start();                Thread t2 = new MyRunner(50);        t2.setDaemon(true);        t2.setName("后台线程t2");        t2.start();                for(int i=0;i<10;i++){            System.out.println(Thread.currentThread().getName() + ": " + i);            }        System.out.println("主线程结束!");    }}class MyRunner extends Thread {    private int n;    public MyRunner(int n){        this.n = n;        }    public void run() {        for(int i=0; i<n; i++) {                    System.out.println(this.getName() + ": " + i);        }        System.out.println(this.getName() + "结束!");    }}

 

结果:

用户线程t1: 0用户线程t1: 1用户线程t1: 2用户线程t1: 3用户线程t1: 4用户线程t1: 5用户线程t1: 6用户线程t1: 7用户线程t1: 8用户线程t1: 9用户线程t1结束!main: 0main: 1main: 2main: 3main: 4main: 5main: 6main: 7main: 8main: 9主线程结束!后台线程t2: 0后台线程t2: 1后台线程t2: 2后台线程t2: 3后台线程t2: 4后台线程t2: 5后台线程t2: 6后台线程t2: 7后台线程t2: 8后台线程t2: 9后台线程t2: 10后台线程t2: 11后台线程t2: 12后台线程t2: 13后台线程t2: 14后台线程t2: 15后台线程t2: 16后台线程t2: 17后台线程t2: 18后台线程t2: 19后台线程t2: 20后台线程t2: 21后台线程t2: 22后台线程t2: 23后台线程t2: 24后台线程t2: 25后台线程t2: 26后台线程t2: 27后台线程t2: 28后台线程t2: 29后台线程t2: 30后台线程t2: 31后台线程t2: 32后台线程t2: 33后台线程t2: 34后台线程t2: 35后台线程t2: 36后台线程t2: 37后台线程t2: 38后台线程t2: 39后台线程t2: 40后台线程t2: 41后台线程t2: 42后台线程t2: 43后台线程t2: 44后台线程t2: 45后台线程t2: 46后台线程t2: 47后台线程t2: 48后台线程t2: 49后台线程t2结束!

 

6.GUI线程

GUI程序运行过程中系统会自动创建若干GUI线程

常见GUI线程:

AWT-Windows线程:(windows 系统中)后台线程

AWT-EventQueue-n线程

AWT-Shutdown线程:负责关闭窗体中的抽象窗口工具

 

DestroyJavaVM线程:不是GUI线程,它是当main线程结束之后系统自动创建的,用于等到所有的线程都死掉了之后销毁jvm

 

实例:

package v512.chap16;import java.awt.*;import java.awt.event.*;public class TestGUIThread {        public static void main(String args[]) throws Exception{        Frame f = new Frame();        Button b = new Button("Press Me!");        MyMonitor mm = new MyMonitor();        b.addActionListener(mm);        f.addWindowListener(mm);            f.add(b,"Center");            f.setSize(100,60);        f.setVisible(true);        MyThreadViewer.view();    }}class MyMonitor extends WindowAdapter implements ActionListener{    public void actionPerformed(ActionEvent e){        MyThreadViewer.view();        }}class MyThreadViewer{    public static void view(){        Thread current = Thread.currentThread();        System.out.println("当前线程名称: " + current.getName());        int total = Thread.activeCount();        System.out.println("活动线程总数: " + total + "个");        Thread[] threads = new Thread[total];                current.enumerate(threads);        for(Thread t : threads){            String role = t.isDaemon()?"后台线程 ":"用户线程 ";            System.out.println("   -" + role + t.getName());            }            System.out.println("----------------------------------");    }    }

运行之后,在点击一下 button

输出结果:

当前线程名称: main活动线程总数: 4个   -用户线程 main   -用户线程 AWT-Shutdown   -后台线程 AWT-Windows   -用户线程 AWT-EventQueue-0----------------------------------当前线程名称: AWT-EventQueue-0活动线程总数: 4个   -用户线程 AWT-Shutdown   -后台线程 AWT-Windows   -用户线程 AWT-EventQueue-0   -用户线程 DestroyJavaVM----------------------------------

 

7.线程的生命周期

新建状态

就绪状态:此时不一定马上就开始运行                                                      

运行状态:运行状态的线程可能会发生问题(赚到了阻塞状态)

阻塞状态

终止状态

 

3

 

8.线程的优先级

线程的优先级用数字来表示,范围从1到10。主线程的缺省优先级是5,子线程的优先级默认与其父线程相同。

注意:程序中不能依赖线程的优先级来让线程按照我们的要求来执行!

Thread类提供的相关方法:

public final int getPriority();

public final void setPriority(int newPriority);

相关静态整型常量:

Thread.MIN_PRIORITY = 1

Thread.MAX_PRIORITY = 10

Thread.NORM_PRIORITY = 5

用法举例:

package v512.chap16;public class TestPriority {        public static void main(String args[]){        System.out.println("线程名\t优先级");        Thread current = Thread.currentThread();        System.out.print(current.getName() + "\t");        System.out.println(current.getPriority());                Thread t1 = new Runner();        Thread t2 = new Runner();        Thread t3 = new Runner();        t1.setName("First");                t2.setName("Second");                t3.setName("Third");                t2.setPriority(Thread.MAX_PRIORITY);        t3.setPriority(8);           t1.start();        t2.start();           t3.start();    }}class Runner extends Thread {    public void run() {        System.out.print(this.getName() + "\t");        System.out.println(this.getPriority());            }}

输出结果:

线程名    优先级main    5First    5Second    10Third    8

9.线程的串行化

在多线程程序中,如果在一个线程运行的过程中要用到另一个线程的运行结果,则可进行线程的串型化处理。

Thread类提供的相关方法:

public final void join()

public final void join(long millis)  //等待毫秒数

public final void join(long millis,int nanos)

 

测试 主线程必须要等到子线程运行完成之后才可以运行:

package v512.chap16;public class TestJoin {        public static void main(String args[]){        MyRunner2 r = new MyRunner2();        Thread t = new Thread(r);        t.start();        try{            t.join();        }catch(InterruptedException e){            e.printStackTrace();        }        for(int i=0;i<20;i++){            System.out.println("主线程:" + i);        }    }}class MyRunner2 implements Runnable {    public void run() {        for(int i=0;i<20;i++) {            System.out.println("SubThread: " + i);        }    }}

输出结果:

SubThread: 0SubThread: 1SubThread: 2SubThread: 3SubThread: 4SubThread: 5SubThread: 6SubThread: 7SubThread: 8SubThread: 9SubThread: 10SubThread: 11SubThread: 12SubThread: 13SubThread: 14SubThread: 15SubThread: 16SubThread: 17SubThread: 18SubThread: 19主线程:0主线程:1主线程:2主线程:3主线程:4主线程:5主线程:6主线程:7主线程:8主线程:9主线程:10主线程:11主线程:12主线程:13主线程:14主线程:15主线程:16主线程:17主线程:18主线程:19

10.线程休眠

线程休眠——暂停执行当前运行中的线程,使之进入阻塞状态,待经过指定的“延迟时间”后再醒来并转入到就绪状态。

Thread类提供的相关方法:

public static void sleep(long millis)

public static void sleep(long millis, int nanos)

用法举例: 数字时钟

package v512.chap16;import java.util.*;import javax.swing.*;public class DigitalClock{    public static void main(String[] args){        JFrame jf = new JFrame("Clock");        JLabel clock = new JLabel("Clock");        clock.setHorizontalAlignment(JLabel.CENTER);        jf.add(clock,"Center");        jf.setSize(140,80);        jf.setLocation(500,300);        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        jf.setVisible(true);                while(true){            clock.setText(getTime());            try{                Thread.sleep(1000); //this.sleep(1000);                }catch(InterruptedException e){                e.printStackTrace();                }            }        }    public static String getTime(){        Calendar c = new GregorianCalendar();        String time = c.get(Calendar.YEAR) + "-" +                      (c.get(Calendar.MONTH) + 1) + "-" +                      c.get(Calendar.DATE)  + "  " ;        int h = c.get(Calendar.HOUR_OF_DAY);        int m = c.get(Calendar.MINUTE);        int s = c.get(Calendar.SECOND);        String ph = h<10 ? "0":"";        String pm = m<10 ? "0":"";        String ps = s<10 ? "0":"";                time += ph + h + ":" + pm + m + ":" + ps + s;         return time;    }    }

显示效果:

4

 

11.线程让步

线程让步——让运行中的线程主动放弃当前获得的 CPU 处理机会,但不是使该线程阻塞,而是使之转入就绪状态。

Thread类提供的相关方法:

public static void yield()

用法举例:

package v512.chap16;import java.util.Date;public class TestYield{    public static void main(String[] args){        Thread t1 = new MyThread(false);        Thread t2 = new MyThread(true);        Thread t3 = new MyThread(false);        t1.start();        t2.start();        t3.start();    }    }class MyThread extends Thread{    private boolean flag;    public MyThread(boolean flag){        this.flag = flag;    }    public void setFlag(boolean flag){        this.flag = flag;    }    public void run(){        long start = new Date().getTime();        for(int i=0;i<500;i++){            if(flag)                Thread.yield();            System.out.print(this.getName() + ": " + i + "\t");        }        long end = new Date().getTime();        System.out.println("\n" + this.getName() + "执行时间: " + (end - start) + "毫秒");    }}

输出结果太多了,不便贴出,可以查看一下执行时间

Thread-0执行时间: 67毫秒

Thread-2执行时间: 84毫秒

Thread-1执行时间: 148毫秒

 

12.线程的挂起和恢复

线程挂起——暂时停止当前运行中的线程,使之转入阻塞状态,并且不会自动恢复运行。

线程恢复——使得一个已挂起的线程恢复运行。

Thread类提供的相关方法:

public final void suspend()

public final void resume()

用法举例:

package v512.chap16;import java.awt.Color;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.util.Date;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JButton;public class TestSuspend{    public static void main(String[] args){        JFrame jf = new JFrame("Timer");        JButton pause = new JButton("Pause");        JLabel clock = new JLabel("Timer");        clock.setBackground(Color.GREEN);        clock.setOpaque(true);        clock.setHorizontalAlignment(JLabel.CENTER);        jf.add(clock,"Center");        jf.add(pause,"North");        jf.setSize(140,80);        jf.setLocation(500,300);        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        jf.setVisible(true);        MyThread3 mt = new MyThread3(clock,10000);        mt.start();        MyListener ml = new MyListener(clock,mt);        pause.addActionListener(ml);    }    }class MyThread3 extends Thread{    private JLabel clock;    private long time;    private long end;        public MyThread3(JLabel clock,long time){        this.clock = clock;            this.time = time;    }    public void init(){        long start = new Date().getTime();        end = start + time;    }        public void run(){        this.init();        while(true){            long now = new Date().getTime();            time = end - now;            if(time > 0){                String s = this.convert(time);                    clock.setText(s);            }else{                break;                }            try{                Thread.sleep(10);                }catch(InterruptedException e){                e.printStackTrace();                }        }        clock.setText("时间到!");            clock.setBackground(Color.RED);    }        public String convert(long time){        long h = time / 3600000;        long m = (time % 3600000) / 60000;        long s = (time % 60000) / 1000;        long ms = (time % 1000) / 10;        String ph = h<10 ? "0":"";        String pm = m<10 ? "0":"";        String ps = s<10 ? "0":"";            String pms = ms<10 ? "0":"";            String txt = ph + h + ":" + pm + m + ":" + ps + s + "." + pms + ms;         return txt;    }    }class MyListener implements ActionListener{    private JLabel clock;    private MyThread3 mt;    private boolean running= true;        public MyListener(JLabel clock,MyThread3 mt){        this.clock = clock;        this.mt = mt;    }        public void actionPerformed(ActionEvent e){        if(!mt.isAlive())            return;        JButton jb = (JButton)(e.getSource());        if(running){            jb.setText("Replay");            clock.setBackground(Color.YELLOW);            mt.suspend();        }else{            jb.setText("Pause");            clock.setBackground(Color.green);            mt.init();            mt.resume();        }        running = !running;    }    }

 

测试结果:

5     6     7

 

13.终止线程

一种特别优雅的方式终止线程(设置标志 flag)

实例:

public class Test {    public static void main(String args[]){        Runner r = new Runner();        Thread t = new Thread(r);        t.start();        for(int i=0;i<10;i++){            try{                Thread.sleep(5);                System.out.println("\nin thread main i=" + i);            }catch(InterruptedException e){                e.printStackTrace();            }        }        System.out.println("Thread main is over");        r.shutDown();    }}
public class Runner implements Runnable {    private boolean flag=true;    public void run() {        int i = 0;        while (flag == true) {            System.out.print(" " + i++);        }    }    public void shutDown() {        flag = false;    }}

main线程结束之后,子线程也就结束了(flag == false)

 

14.线程控制的基本方法

8

 

 

15. 临界资源问题

临界资源问题实例:

两个线程A和B在同时操纵Stack类的同一个实例(栈),A向栈里push一个数据,B则要从堆栈中pop一个数据。

栈的模拟public class Stack{        int idx=0;        char[ ] data = new char[6];        public void push(char c){            data[idx] = c;            idx++;        }        public char pop(){            idx--;            return data[idx];        }    }

可能出现的问题

9

 

(4 中 c 应该是不存在的)

 

16. 互斥锁 和 死锁

在Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。

每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。

关键字synchronized 来与对象的互斥锁联系。当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问。

synchronized用法

①用于方法声明中,标明整个方法为同步方法:这个时候调用这个方法的对象是处于被当前的线程锁定的状态

    public synchronized void push(char c){                data[idx] = c;                idx++;        }

②用于修饰语句快,标明整个语句块为同步块:这个时候 synchronized  中的对象是被当前的线程锁定了的

    public char pop(){            //其它代码            synchronized(this){                    idx--;                    return data[idx];            }            //其它代码    }

并发运行的多个线程间彼此等待、都无法运行的状态称为线程死锁。

线程死锁实例一:

package v512.chap16;public class TestDeadLock{    public static void main(String args[]){        StringBuffer sb = new StringBuffer("ABCD");        MyThread4 t = new MyThread4(sb);        t.start();            synchronized(sb){            try{                t.join();            }catch(InterruptedException e){                e.printStackTrace();                }            System.out.println(sb);            }        System.out.println("Main thread is over!");        }    }class MyThread4 extends Thread{    private StringBuffer sb;    public MyThread4(StringBuffer sb){        this.sb = sb;    }    public void run(){        synchronized(sb){            sb.reverse();        }        System.out.println("Sub thread is over!");        }    }

控制台什么都没有输出来!

分析:在main方法的同步块中串行插入了子线程t,并锁定了sb对象,然而子线程的run方法中也有一个同步块,它要锁定的对象正是sb对象,

然而sb对象已经被主线程给锁定了,子线程只能等待,另一方面,主线程又必须要等到子线程结束了之后才可以执行,两者就这么一直等待着,

陷入了死锁的状态!

如果删除掉main中的同步,就可以看到结果:

Sub thread is over!DCBAMain thread is over!

 

实例二:

package v512.chap16;public class TestDeadLock2{    public static void main(String args[]){        char[] a = {'A','B','C'};        char[] b = {'D','E','F'};        MyThread5 t1 = new MyThread5(a,b);        MyThread5 t2 = new MyThread5(b,a);        t1.start();        t2.start();            }    }class MyThread5 extends Thread{    private char[] source;    private char[] dest;        public MyThread5(char[] source,char[] dest){        this.source = source;        this.dest = dest;    }    public void run(){        synchronized(source){            try{                Thread.sleep(1000);            }catch(InterruptedException e){                e.printStackTrace();                }                        synchronized(dest){                System.arraycopy(source,0,dest,0,source.length);                System.out.println(dest);            }                }    }    }

 

假设线程t1先执行run,然后将字符数组a锁定了,接着t1休眠了,线程t2开始执行,并将数组b锁定了,之后线程t2进入休眠,

然后线程t1重新执行,这时候发现数组b已经被线程t2给锁定了,只能等待,休眠之后,线程t2同样发现数组a被线程t1给锁定了,

两者相互之间等待着,就陷入了死锁状态!

 

17.线程的同步通信

为避免死锁,在线程进入阻塞状态时应尽量释放其锁定的资源,以为其他的线程提供运行的机会。

相关方法:

public final void wait() :会导致当前的线程进入阻塞状态并尽量释放其锁定的资源

public final void notify():将某个线程重新恢复过来,但不是马上就进入到就绪状态,它可能还要等,等到它要使用的对象解除了锁定才行

public final void notifyAll()

10

 

生产者 和 消费者 问题:

同步的栈:

package v512.chap16;public class SyncStack { // 支持多线程同步操作的堆栈的实现    private int index = 0;    private char[] data = new char[6];    public synchronized void push(char c) {        while (index == data.length) {            try {                this.wait();            } catch (InterruptedException e) {            }        }        this.notify();        data[index] = c;        index++;        System.out.println("produced:" + c);    }    public synchronized char pop() {        while (index == 0) {            try {                this.wait();            } catch (InterruptedException e) {            }        }        this.notify();        index--;        System.out.println("consumed:" + data[index]);        return data[index];    }}

 

测试类:包括了生产者和消费者

package v512.chap16;public class SyncTest{    public static void main(String args[]){        SyncStack stack = new SyncStack();        Runnable p=new Producer(stack);        Runnable c = new Consumer(stack);        Thread t1 = new Thread(p);        Thread t2 = new Thread(c);        t1.start();        t2.start();    }}class  Producer implements Runnable{    SyncStack stack;        public Producer(SyncStack s){        stack = s;    }    public void run(){        for(int i=0; i<20; i++){            char c =(char)(Math.random()*26+'A');            stack.push(c);            try{                                                    Thread.sleep((int)(Math.random()*300));            }catch(InterruptedException e){            }        }    }}class Consumer implements Runnable{    SyncStack stack;        public Consumer(SyncStack s){        stack = s;    }    public void run(){        for(int i=0;i<20;i++){            char c = stack.pop();            try{                                                       Thread.sleep((int)(Math.random()*500));            }catch(InterruptedException e){            }        }    }}

 

输出结果:

produced:Mconsumed:Mproduced:Nconsumed:Nproduced:Pproduced:Aconsumed:Aconsumed:Pproduced:Zconsumed:Zproduced:Fproduced:Jproduced:Xproduced:Qconsumed:Qproduced:Nproduced:Wproduced:Kconsumed:Kproduced:Iconsumed:Iproduced:Aconsumed:Aproduced:Zconsumed:Zproduced:Mconsumed:Mproduced:Xconsumed:Xproduced:Xconsumed:Xproduced:Pconsumed:Pproduced:Vconsumed:Vconsumed:Wconsumed:Nconsumed:Xconsumed:Jconsumed:F

 

18.多线程编程专题  (还未仔细看)

线程间数据传输

例16-16 使用管道流实现线程间数据传输

类的同步性与线程安全

例16-17 验证同步类的线程安全性

定时器

例16-18 使用定时器实现数字时钟功能





gc机制

    博客分类: 
  • java
gc
一、谁在做Garbage collection 
垃圾回收机制是放在JVM中,由JVM来负责回收垃圾,我们只需要创建对象来分配空间,当对象无用时则不用担心空间回收的问题。 
二、对象什么时候被回收 
对象的生命周期与作用域无关,与引用有关。当一个对象被多个引用所指向,当该对象不再有任何引用指向它时,这个对象就被抛弃了,就可以被垃圾回收机制回收。比如当某个对象不存在任何引用时,引用告诉jvm你可以回收这个对象了,它对于我来说没有用了。 
当jvm的垃圾回收机制对堆空间做检测时,发现某个对象的引用数为0时,就会把这个对象列入待回收列表中,并不是马上就销毁。 
当一个对象被认为没有必要存在了,则会释放它占用的内存,被释放的内存可以再分配。但是并不是立刻就被回收的,jvm进程做空间回收有较大的系统开销,如果一个对象被丢弃就立刻回收它,会使整个应用的运转效率非常低下,jvm的垃圾回收机制有很多算法,除了引用计数法用来判断对象是否被抛弃外,其他算法是用来确定何时与如何做回收。为了提高效率,垃圾回收器通常在满足两个条件才运行:有对象要被回收,系统需要回收。因此运行时系统只在需要的时候才使用它,所以你不知道垃圾回收发生的准确时间。 
三、没有引用指向的对象有用么? 
没有引用指向的对象是要被回收的,是堆空间里的一个垃圾。但是有个例外,对于一次性使用的对象(临时对象)。可以不用引用变量指向它。例如:System.out.print("I like Java");就是创建了一个字符串对象后,无引用指向,直接传递给println()方法。 
四、应用能干预垃圾回收吗? 
这是不能的,对于垃圾回收机制来说,应用只有两个途径发消息给JVM,第一个就是指向某对象的引用全部移除了,这个对象不要了;第二个就是调用方法System.gc()。 
对于system.gc()来说这也仅仅是个请求,JVM接受这个消息后并不是立即做垃圾回收,而只是对几个垃圾回收算法做了加权,使垃圾回收操作容易发生,或提早发生,或回收较多而已。 
Java的垃圾回收机制是为所有java应用进程服务的,而不是为个特定的进程服务的,所以任何进程都不能命令垃圾回收机制做什么、怎么做或做多少。
  • JAVA多线程编程详解-详细操作例子.rar (4.9 MB)
  • 下载次数: 24

原创粉丝点击