java中线程基础总结

1.线程的创建方式

  1.继承Thread并重写run方法,run方法是用来定义当前线程

public class ThreadDemo1 {
    public static void main(String[] args) {
        Thread t1 = new MyThread1();
        Thread t2 = new MyThread2();
        /*
         * 启动线程要调用start方法而不是run方法。
         * 当start方法调用完毕后,run方法很快
         * 的被自动执行。
         */
        t1.start();
        t2.start();
        
    }
}
/*
 * 继承线程重写run方法这样的做法有两个不足:
 * 1.由于java是单继承,这就导致继承了Thread就不能继承
 * 其他类。
 * 2.由于重写run方法将线程的任务定义在了线程当中,这就
 * 导致线程的重用性变得很差。线程与任务不应有必然的耦合关系。
 */

class MyThread1 extends Thread{
    public void run(){
        for(int i = 0;i<1000;i++){
            System.out.println("你是谁啊");
        }
    }
}
class MyThread2 extends Thread{
    public void run(){
        for(int i = 0;i<1000;i++){
            System.out.println("我是你爸爸");
        }
    }
}
View Code

  2.实现Runable接口单独定义线程任务

public class ThreadDemo2 {
    public static void main(String[] args) {
        Runnable r1 = new MyRunnable1();
        Runnable r2 = new MyRunnable2();
        
        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r2);
        t1.start();
        t2.start();
    }
}
class MyRunnable1 implements Runnable{
    public void run(){
        for(int i=0;i<1000;i++){
            System.out.println("你是谁啊");
        }
    }
}
class MyRunnable2 implements Runnable{
    public void run(){
        for(int i= 0;i<1000;i++){
            System.out.println("我是你爸爸");
        }
    }
}
View Code

      3.使用匿名内部类来完成两种方式的线程创建

public class ThreadDemo3 {
    public static void main(String[] args) {
      Thread t1 = new Thread(){
          public void run(){
                for(int i=0;i<1000;i++){
                    System.out.println("你是谁啊");
                }
            }
      };
      Thread t2 = new Thread(new Runnable(){
          public void run(){
                for(int i = 0;i<1000;i++){
                    System.out.println("我是你爸爸");
                }
            }
      });
      t1.start();
      t2.start();
    }
}
View Code

2.线程的优先级

/**
 * 线程优先级
 * 
 * 线程对线程调度的工作是不可控的,即:
 * 线程只能被动被分配CPU时间,而不能主动获取到。
 * 
 * 线程调度会尽可能的将CPU时间分配的几率做到均匀。但是
 * 多个线程开发运行,并不保证一个线程一次这样交替运行。
 * 
 * 可以通过调整线程的优先级改善分配CPU时间片几率。
 * 理论上线程优先级越高的线程,获取CPU时间片的次数就多。
 * 
 * 线程的优先级有10级,分别用整数1-10表示
 * 其中1最低,5默认,10最高
 * @author tarena
 *
 */
public class Thread_setPriorty {

    public static void main(String[] args) {
        Thread max = new Thread(){
            public void run(){
                for(int i=0;i<10000;i++){
                    System.out.println("max");
                }
            }
        };
        Thread mor = new Thread(){
            public void run (){
                for(int i=0;i<10000;i++){
                    System.out.println("mor");
                }
            }
        };
        Thread min = new Thread(){
            public void run(){
                for(int i = 0;i<10000;i++){
                    System.out.println("min");
                }
            }
        };
        //改变线程的优先级
    max.setPriority(Thread.MAX_PRIORITY);
    min.setPriority(Thread.MIN_PRIORITY);
    
    min.start();
    mor.start();
    max.start();
    }
}
View Code

3.守护线程的使用

/**
 * 守护线程,又称为:后台线程
 * 使用上与前台线程并无区别,所有线程默认创建出来都是
 * 前台线程,想变为守护线程需要单独设置。
 * 
 * 但是结束时机上有一点不同:
 * 当进程结束时,所有正在运行的守护线程都会被强制结束。
 * 而一个进程中所有前台线程都结束,进程就会结束。
 * @author tarena
 *
 */
public class Thread_setDemo {
    public static void main(String[] args) {
        Thread rose = new Thread(){
            public  void run(){
                for(int i=0;i<5;i++){
                    System.out.println("rose:let me go!");
                    try {
                        Thread.sleep(1000);//使线程进入阻塞状态 每隔一秒输出一次for里面的
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("rose:啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊");
                System.out.println("音效:噗通!");
            }
        };
        Thread jack = new Thread(){
            public void run(){
                while(true){
                    System.out.println("jack:you jump  i jump!");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        rose.start();
        //设置守护线程必须在线程启动前进行
        jack.setDaemon(true);
        jack.start(); 
    
    }
}
View Code

4.线程的相关属性

public class Thread_Info {

    public static void main(String[] args) {
        //取运行main方法的线程
        Thread main = Thread.currentThread();
        //获取线程ID
        long id = main.getId();
        System.out.println("id:"+id);
        //获取线程名
        String name = main.getName();
        System.out.println("name:"+name);
       //是否处于活动状态
        boolean isAlive = main.isAlive();
        System.out.println("isAlive:"+isAlive);
        //是否为守护线程
        boolean isDaemon = main.isDaemon();
        System.out.println("isDaemon:"+isDaemon);
        //是否是被中断
        boolean isInterrupted = main.isInterrupted();
        System.out.println("isInterrupted:"+isInterrupted);
    }

}
View Code

5.线程的阻塞,join方法

/**
 * 线程是异步运行的
 * 异步:合执行各的,互相不妨碍
 * 同步:有先后顺序的执行。
 * 
 * 有些业务需要让多个线程同时同步进行,这时候可以借助线程的join方法来完成
 * 
 * join方法允许一个线程进入阻塞状态,直到其等待的另一个线程工作结束后再继续运行。
 */
public class Thread_join {
    public static boolean isFinish = false;
    public static void main(String[] args) {
    final    Thread download = new Thread(){
            public void run(){
                System.out.println("dowm:开始下载图片...");
                for(int i = 1;i<=100;i++){
                    System.out.println("down:"+i+"%");
                    try {
                        Thread.sleep(10);//阻塞
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("down:图片下载完毕!");
                isFinish = true;
            }
        };
        Thread show = new Thread(){
            public void run(){
                System.out.println("show:开始显示图片...");
                try {
                    download.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                /*
                 * 先等待下载线程将图片下载完毕,再加载
                 */
                if(!isFinish){
                    throw new RuntimeException("图片加载失败!");
                }
                System.out.println("show:显示图片完毕!");
            }
        };
        download.start();
        show.start();
    }
}
View Code

6.线程池的使用

/**
 * 线程池
 * 线程池通常用于:
 * 1.控制线程数量
 * 2.重用线程
 * 
 * @author tarena
 *
 */
public class ThreadPoolDemo {
    public static void main(String[] args) {
    ExecutorService threadPoo1 = Executors.newFixedThreadPool(2);//线程池中包含了2个线程
        for(int i = 0;i<5;i++){//5个任务 
            Runnable runn = new Runnable(){
                public void run(){
                    Thread t = Thread.currentThread();
                    System.out.println(t.getName()+":正在执行任务");
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                    }
                    System.out.println(t.getName()+":任务执行完毕");
                }
            };
            threadPoo1.execute(runn);
            System.out.println("将任务"+i+"指派给线程池");
        }
        //停止线程池
        threadPoo1.shutdownNow();
        System.out.println("停止了线程池");
    }
}
View Code

线程小知识:

  线程存在多线程并发安全问题,即当多个线程同时操作同一资源时,会出现“抢”的情况。由于多线程切换时机不定,可能导致代码执行顺序出现混乱,有悖于程序设计的执行顺序而出现逻辑错误,严重时可能导致系统瘫痪。

原文地址:https://www.cnblogs.com/zblwyj/p/10845611.html