首页 > 代码库 > Java线程学习笔记(一)

Java线程学习笔记(一)

一、线程的创建方式:

老掉牙的话题了,继承 java.lang.Thread父类或者实现Runnalbe接口,这里就提一句:

class Thread implements Runnable
Thread也是继承了Runnable接口的,Runnable才是大哥。

重写run(),run()里放的都是具体的业务,包括对线程的具体操作。

class Thread1 implements Runnable {
    int i;
    Thread1(int i) {
        this.i = i;
    }
    @Override
    public void run() {
        long x = new Random().nextInt(10)*1000;
        try {
            Thread.sleep(x);
        } catch (InterruptedException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        System.out.println("线程"+ i + "睡眠" + x);
    }
}
二、线程的调用:

独立的线程启动方式—Thread的start()方式,

class Thread1Execute {
    public static void main(String[] args) {
        // 创建线程
        Thread thread = new Thread(new Thread1(99));
        // 启动命令
        thread.start();
    }
}
线程池启动 ExecutorService

public class SleepTest1 {
    public static void main(String[] args) {
        // 创建线程池,这里用了向上造型,其实newCachedThreadPool出来的类是ThreadPoolExecutor。
        ExecutorService executor = Executors.newCachedThreadPool();
        for (int i=0;i<10 ; i++) {
            // 执行10个线程
            executor.execute(new Thread1(i));
        }
        //关闭线程池 
        executor.shutdown();
    }
}

三、线程优先级:

线程里设置优先级,JDK里有10个优先级,但JDK得优先级与操作系统兼容的并不好,因此,在编程的时候,只是用三个优先级

   /**
     * The minimum priority that a thread can have. 
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread. 
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have. 
     */
    public final static int MAX_PRIORITY = 10;</span>

设置优先级的代码要放到run()的开头部分。

public void run() {
    // 设置优先级为最高。
    Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
}

四、让步Thread.yield()

yield()方法只不过是一个暗示,不能保证它被采用,因此,在对重要的线程进行控制的时候,慎用。

五、后台线程

后台线程也叫守护线程,顾名思义就是在后台跑的线程,不会因正常线程的结束而结束。 

设置方法为,在线程启动之前,thread.setDaemon(true);

因为Thread默认的daemon是false,参照代码如下:

/* Whether or not the thread is a daemon thread. */
    private boolean    daemon = false;
代码示例:

class Thread1Execute {
    public static void main(String[] args) throws InterruptedException {
        for (int i=0;i<10 ; i++) {
            // 创建线程
            Thread thread = new Thread(new Thread1(i));
            thread.setDaemon(true);
            // 启动命令
            thread.start();
        }
        System.out.println("main睡眠");
        Thread.sleep(10000);
        System.out.println("main醒来");
    }
}
输出结果为:

main睡眠
线程6睡眠2000
线程8睡眠2000
线程3睡眠3000
线程7睡眠4000
线程1睡眠5000
线程0睡眠5000
线程9睡眠5000
线程5睡眠7000
线程4睡眠8000
线程2睡眠8000
main醒来

可以看出,后台进程不受Main线程的控制,在main睡眠期间,他们依然辛劳耕种。

但当最后一个非后台线程退出时,后台线程会“突然”终止,也就是说一旦main()退出,JVM将关闭所有后台线程。

因此,这种后台线程并不好控制,不推荐在实际项目中使用。


还有一种线程池的创建后台进程的方式,这种方式稍微有那么一点点复杂

Executors.newCachedThreadPool(new DaemonThreadFactory());这里需要传入一个线程工厂。

public static void main(String[] args) throws Exception {
        ExecutorService exec = Executors.newCachedThreadPool(new DaemonThreadFactory());
        for(int i = 0; i < 10; i++)
            exec.execute(new DaemonFromFactory());
        System.out.println("All daemons started");
        TimeUnit.MILLISECONDS.sleep(500); // Run for a while
    }
工厂的定义如下,作用为将所有创建出来的线程都设置为Daemon后台线程类型。
class DaemonThreadFactory implements ThreadFactory {
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    }
}

这种灵感来源于java.util.concurrent.Executors的默认线程工厂。

   /**
     * The default thread factory
     */
    static class DefaultThreadFactory implements ThreadFactory {
        static final AtomicInteger poolNumber = new AtomicInteger(1);
        final ThreadGroup group;
        final AtomicInteger threadNumber = new AtomicInteger(1);
        final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null)? s.getThreadGroup() :
                                 Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }



先讲这么多,线程这块的东西实在是太多了,理解起来也非常难。有那么一本书推荐一下《JAVA并发编程实践》这本书是专门讲并发的,我打算下个月就开始写那本书的阅读日记,当然还有传说中的《Head first设计模式》。