JAVA多线程基础知识

来源:互联网 发布:淘宝上被骗怎么投诉 编辑:程序博客网 时间:2024/05/17 23:07

开篇       

        毕业三四年了,一直没怎么用过多线程,一直停留在继承Thread 和 实现Runnable接口上,最近开始写多线程了发现没我想象那么简单,今天开始从头过一遍java的多线程的知识包括最基础的细节,希望对后面的开发以及以后的面试有所帮助。

进程与线程

  1.        说到进程,打开我们操作系统的任务管理器->进程,这里应该不用多说了。看看官方解释:进程是操作系统结构的基础;是一次程序的运行;它是系统进行资源分配和调度的一个单位。
  2.       线程是进程中独立运行的子任务。
  3.      一个进程在运行时至少有一个线程,一个mian方法就是一个进程,同时默认有一个线程。
  4.      多线程是异步的,不是代码上下执行的顺序。

使用多线程

   这里我就不多说了,看看Thread的源代码,它也是实现了Runnable的接口,java不能多继承,因此两种方式类似,我就直接贴代码了。

继承Thread

 

package thread.t001;public class MyThread extends Thread {@Overridepublic void run() {System.out.println("MyThread"+Thread.currentThread().getName());}public static void main(String[] args) {MyThread m = new MyThread();m.start();}}

实现Runnable接口

package thread.t001;public class MyThread2 implements Runnable{public void run() {System.out.println("Runnable: "+Thread.currentThread().getName());}public static void main(String[] args) {MyThread2 m = new MyThread2();Thread t = new Thread(m);t.start();}}

以上两种的调用方法看似有点区别,其实实质是一样的。调用Thread的start方法,执行多线程类的run()方法

注意几点,同一个线程不能多次start会报

Exception in thread "main" java.lang.IllegalThreadStateException
异常

实例变量与线程安全

不共享数据

package thread.t001;public class MyTask extends Thread{    int count = 5;    @Override     public void run() {        while(count > 0){            count--;            System.out.println(Thread.currentThread().getName()+":"+count);            };    }        public static void main(String[] args) {            MyTask t1 = new MyTask();        t1.start();        MyTask t2 = new MyTask();        t2.start();    }}

结果:

Thread-0:4Thread-0:3Thread-0:2Thread-0:1Thread-0:0Thread-1:4Thread-1:3Thread-1:2Thread-1:1Thread-1:0

共享数据

package thread.t001;public class MyTask extends Thread{    int count = 5;    @Override    synchronized public void run() {        while(count > 0){            count--;            System.out.println(Thread.currentThread().getName()+":"+count);            };    }        public static void main(String[] args) {            MyTask t1 = new MyTask();        Thread t = new Thread(t1);        t.start();        Thread t2 = new Thread(t1);        t2.start();    }}

结果:

Thread-1:4Thread-2:3Thread-1:2Thread-2:1Thread-1:0
通过上面两段代码可以发现,共享数据只创建了一次资源,用两个线程去跑,结果是两个线程共同消费了count,但是细心地你发现了共享数据的方法前加了synchronized关键字这个稍后说;

但是不共享数据的没有加,这是因为共享资源的多线程中,线程是不安全的,因为多个线程操作的同一个资源count,如果count变量做为该方法的局部变量,则是线程安全的。

多线程常用方法

currentThread()方法可返回代码段正在被哪个线程调用的信息;

isAlive()方法判断当前的线程是否处于活动状态;

sleep()的作用是在制定的毫秒书内让当前正在执行的线程休眠;

getId()方法的作用是取得线程的唯一标示;

以上方法就不一一且代码测试了,重点看一下停止一个线程interrupt(0方法

停止一个线程

简单粗暴的方法是是stop();
调用stop()会报出java.lang.ThreadDeath异常,此异常不需要显示的扑捉,stop()方法jdk已不再建议使用,

使用stop()方法如果强制让线程停止侧有可能使一些清理性的工作得不到完成
对锁定的对象进行了“解锁”,导致数据得不到同步的处理,出现数据不一致的问题

停止一个线程有以下几种办法:

interrupt -> isterrupt -> return

interrupt -> isterrupt -> break

interrupt -> isterrupt -> throw exception

需要用到isterrupt()方法配合使用或者interrupted()方法,判断是否为true

我举一个例子说明下,其它方法类似:

package thread.t001;public class MyInterrupt extends Thread {@Overridepublic void run() {try {for (int i=0; i<100; i++){if (i == 50){Thread.currentThread().interrupt();if (Thread.currentThread().interrupted()){throw new InterruptedException();}}System.out.println(i);}System.out.println("我是run的结尾!");} catch (Exception e) {}}}

加粗两三句代码可结束一个线程,
Thread.currentThread().interrupt();
将此线程标记为停止状态为true

Thread.currentThread().interrupted()
如果此线程为停止状态

throw new InterruptedException();
抛出一个异常跳出;这一步可以用break(此方法看逻辑,虽然跳出了循环,但是for下面的还会执行)

通过以上可以得出 interrupt()方法并不是将线程停掉,而是做了一个标记,然后使用interrupted判断此线程的标记,如果标记了则终止;

interrupt()与isterrupt

都可以判断线程当前的状态

interrupt() 判断之后会清空此线程的状态,如果第一次判断为true,则之后再调用则为false

isterrupt()不清空状态

在sleep()状态下停止线程
在sleep()中interrupt 和 interrupt再sleep()都会进入catch

yield()作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间,但放弃时间不确定,有可能刚刚放弃,马上又获得CPU是时间片

suspend()暂停,resume()继续

这两个方法有个缺点就是独占资源,会导致共享的数据其它线程无法访问,也会导致数据不同步(比如给两个值赋值,第一个赋完值暂停了还没有继续,然后其它线程调用了get方法获取这两个值)

线程的优先级别

在操作系统中,线程可以划分优先级,优先级较高的线程得到的CPU资源较多,也就是CPU、优先执行优先级较高的线程对象中的任务
setPriority();优先级级别为1-10

如果小于1或者大于10则会抛出异常

优先级高不一定就先执行完

线程优先级的继承特性
在Java中,线程的优先级具有继承性,比如A线程启动B线程,则B线程的优先级与A线程是一样的

守护线程(Daemon)

Java线程中有两种线程,一种是用户线程,一种是守护线程
守护线程是一种特殊的线程,它的特性有“陪伴”的含义,当进程不存在非守护线程了,则守护线程自动销毁。典型的守护线程就是垃圾回收线程

今天就先学习整理到这里,下一篇重点学习一下 多线程的并发。




0 0
原创粉丝点击