Java多线程基础(一)

提示

文章是阅读《Java多线程编程核心技术》和《Java并发编程的艺术》写的,建议大家都读读,个人意见,
先完成核心技术的阅读,再去读并发编程艺术,感觉并发编程艺术比核心技术深。

开始

从工作开始就发现自己的多线程只了解基础,我想好多刚开始Java开发的人员也多多线程了解的不多,工作起来才发现
多线程多么重要,没别的学起来才是硬道理。学什么都要系统的学一次,别想着偷懒,只了解某一个知识的某一点,那样
只会让自己学的东西越来越乱。

进程和线程

1:进程:现代操作系统一次程序的执行,是程序再一个数据集上运行的过程
    eg:打开QQ,再QQ上做各种操作,都是完成再一个进程。
2:线程:一个进程中执行的一个子任务。现代操作系统执行程序的最小单元,

多线程的优点就不在多说:最大利用CPU资源,更好的编程模型。

使用多线程

 Java自带了对多线程的支持,我们可以很方便的实现多线程
 1:实现Runable接口
 2:继承Thread类,
     查看源码可以发现,Thread类就是实现了Runable接口的类,所以两种方法其实是一种方法,本质一样。
public class MyThead extends Thread {
    @Override
    public void run () {
        super.run();
        System.out.println("MyThread");
    }
}

public class MyRunable implements Runable{
    @Override
    public void run () {
        super.run();
        System.out.println("MyRunable");
    }
}

//main函数执行
public static void main(String [] args) {
    MyThread myThead = new MyThread();
    myThread.start() //多线成开始执行
    myThread = new MyRunable();
    myThread.start();
}

注:多线程的执行顺序与代码执行顺序或调用顺序无关,计算机系统会自己安排运行的时间段,
start方法通知“线程规划器”这个线程准备好了,等待系统安排时间来调用线程的run方法。

Thread类的构造函数

1:Thread():
2:Thread(Runable able) 分配新的Thread对象
3:Thread(Runable target, String name)  name:为线程指定名字
4:Thread(String name)
5:Thread(ThreadGroup group, Runable target) :为线程指定线程组
6:Thread(ThreadGroup group, Runable target, String name);
7:Thread(ThreadGroup group, Runable target, String name, long stackSize)
        long指定线程堆栈的大小。
8:Thread(Threadgroup group, String name)

实例变量和线程安全

自定义线程中实例变量对其他线程有共享和不共享之分,多个线程之间的共享数据
是很重要的一点。

1:不共享变量,每个线程单独享有自己的变量,互不交叉
eg:

public class MyThread extends Thread{
    private int count = 5;
    public MyThread(String name){
        super();   this.setName(name);
    }
    @override
    public void run(){
        super.run();
        while(count > 0){
            count--;
            System.out.println("由" + this.currentThread().getName() + 
                "计算,  count =" + count);
        }
    }
}
//运行main函数
public class Run{   
    public static void main(String[] args){
        MyThread a = new MyThread("A");
        MyThread b = new MyThread("B");
        a.start();  b.start();
    }
}

上例子因为每个线程a b都是新建的对象,对象里的每一个count都是每个线程独有的,不会出现交叉,所以不会出现
共享变量,不会出现线程安全,

2:共享变量

public class Run{
    public static void main(String [] args){
        MyThread myThread = new MyThread("A");
        Thread  a = new Thread(myThread, "A");
        Thread b = new Thread(myThread, "B");
        a.start();
        b.start();
    }
}
上个例子是利用Thread类的构造函数,利用一个实例对象建立两个线程,这时两个线程共享一个实例对象,对象中的
变量也被两个线程共享,这时候就会出现共享变量的线程安全问题。

新名词:非线程安全:

指多个线程对同一个对象的同一个实例变量进行操作时会出现值被更改,值不同步的情况,进而影响程序执行的流程。

方法:

1:currentThread():返回当前代码正在被那个线程调用,
public  class MyThread extends Thread{
    public MyThread(){
        System.out.println(Thread.currentThread().getName());
    }   
    @override
    public void run(){
        System.out.println(Thread.currentThread().getName());
    }
}

public class Run{
    public static void main(String [] args){
        MyThread a = new MyThread();  //这里因为是主线程调用则输出为main
        a.start();    //这里会调用run方法,但是是子线程调用,run方法会输出Thread-0
        a.run();    //这里虽然调用run,但是普通的方法调用没有开启线程,run方法会输出main
    }
}
2:isAlive():判断线程是否处于活跃状态。线程启动但未终止。
    this.isAlive();     myThread.isAlive();
3:sleep(): 在指定时间内让线程休眠,暂停。
    Thread.sleep(1000);
4:getId(); 获取线程的唯一标识,

停止线程

Java有3中退出线程的方法。

  1. 使用退出标志位。使线程正常退出,也就是执行线程的时候判断标志位,让线程直接执行完。
  2. stop方法,这个方法停止线程,但已被废弃,最好不要用它,这个方法不安全,
    会造成各种各样的运行问题和数据问题。、、
  3. 使用interrupt中断线程,
    第三种方法和第一种原理上是一种。
    intertupt方法有两个
    this.interrupted(); 测试-当前-线程是否中断,并清除中断标志未。
    this.isInterrupted() 判断线程是否中断,没有清除功能。
public class Run(){
    public static void main(String [] args){
        MyThread a= new MyThread();
        a.start();
        a.interrupt();//设置中断标志位
        a.interrupted();//  测试当前线程是否中断,虽然是a对象调用的,但是interrupted方法是被main
            (当前线程)调用的,所以会返回false,
        若在a线程的run方法中调用interrupted方法就会返回true,因为a线程已将被interrupt标记中断。
        a.interrupted();// 再次调用返回还是false,因为main线程没有被中断
            但若这个方法再次在a的run方法中调用就会返回false,因为第一次执行会清楚中断标志位。
    }
}

isInterrupted():只是判断线程是否中断,
a.isInterrupted();返回true,

注意:在线程sleep的时候,中断线程,线程就会执行到sleep的catch异常中,并停止线程。

1线层执行异常也会退出线程。

2使用return正常停止线程。

暂停线程

suspend()暂停线程, resume()恢复线程。

线程的优先级

setPriority();设置线程的优先级,优先级越高,得到的CPU资源越多,优先级1~10,别的级别会报异常。

线程优先级的继承性:

当A线程启动B线层时,B线程的优先级与A相同。

注:优先级具有随机性,并不是设置高优先级该线程就一定先执行。

守护线程

Java中分两种线程,用户线程和守护线程。
守护线程是一种特殊的线程,它是守护着用户线程,当没有用户线程活跃时,守护线程自动销毁。垃圾回收线程就是
    典型的守护线程。setDaemon设置线程为守护线程
    eg:   myThread.setDaemon(true);

猜你喜欢

转载自blog.csdn.net/tst116/article/details/79300607