Java 线程 知识

 学习线程 先了解 线程与进程之间的关系

  线程:

 (线程是cpu调度的最小单位)

我们可以说是进程中执行运算的最小单位。

进程:

(进程是资源分配的最小单位)

我们可以说是一段程序执行的过程,

如果还是不清楚2着的话可以打一个比喻 进程 相当于火车, 线程就是火车的没一个车厢. 

-----------------------------------------------------------------------------------------------------------------------------------------------

 创建线程

Java 提供了三种创建线程的方法:

  • 通过实现 Runnable 接口;
  • 通过继承 Thread 类本身;
  • 通过 Callable 和 Future 创建线程。

1 实现Runnable 的接口

 步骤 1.1 建立Runnable 对象

      1.2 使用参数为Runnable 对象的构造方法创建Thread实例

      1.3 调用start方法启动线程

一个小demo

package me;
public class Main{
    public static void main(String[] args){
        Thread thread = new Thread(new Task());
        thread.start();
    }
    static class Task implements Runnable{
        @Override
        public void run() {
            for (int i=0;i<5;i++){
                System.out.println(i);
                try {
                    Thread.sleep(1500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

这个就是创建了一个类Task实现Runnable , 最后创建Thread 然后关联类Task 

2 继承Thread类

package me;

public class Th extends Thread{
    public static void main(String[] args){
        Test test = new Test();
        test.start();
    }
    static class Test extends Thread{
        @Override
        public void run() {
            for (int i=0;i<10;i++){
                System.out.println(i);
                try {
                    Thread.sleep(1500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }

}

因为Test 继承了Thread 所以这里没有在new Thread,

 

3 通过 Callable 和 Future 创建线程。

package me;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class Main implements Callable {
    public static void main(String[] args) {
        Main main = new Main();
        FutureTask futureTask = new FutureTask<>(main);
        Thread thread = new Thread(futureTask);
        thread.start();
    }
    @Override
    public Integer call() throws Exception {
        int i = 0;
        for (; i < 5; i++) {
            System.out.println(i);
            Thread.sleep(1500);
        }
        return i;
    }

}

 

线程的生命周期

 

 

Java 线程 知识_第1张图片

 

这个出生就是创建状态, 就绪状态, 执行状态,等待状态,死亡状态,休眠,阻塞状态

有时候我们看别的地方说5中,6中7中, 其实是吧休眠和阻塞当做一种了,  这个自己心里知道就行,

不过各个状态还是需要知道

 

线程的操作方法

 1 线程休眠 

调用sleep()方法

 例如Thread.sleep(2000) 等待2秒

2 线程加入

 当某个线程使用join()方法加入到另一个线程时,另一个线程等待该线程执行完毕以后在继续执行

 3 线程礼让

使用yield()方法

 yield 方法是具有同样优先级的线程进入可执行状态的机会,

4 中断线程

以前使用stop 不过这个方法已经过时了

现在提倡使用在run()方法里面使用无线循环形式,然后使用一个布尔型标记控制循环停止

Java 线程 知识_第2张图片

 

如果线程使用了sleep()或wait()方法进入就绪状态,可以使用Thread类中的interrupt()方法是线程离开run()方法,同时线程结束

会抛出异常,用户可以处理该异常时完成线程的中断业务处理

线程同步与异步

线程同步使用 Synchronized 关键字 ,

同步可以比喻成大家排队上公交, 异步就是一起上没有顺序

异步的一个demo

package me;
public class Main  {
    public static void main(String[] args) {
        Main demo = new Main();
        //创建2个线程
        new Thread(){
            @Override
            public void run() {
               while (true){
                demo.setName("张三");
               }
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                while (true){
                    demo.setName("李四");
                }
            }
        }.start();

    }

    public void setName(String str){
        for ( int i=0;i

.Java 线程 知识_第3张图片

并没有顺序

同步 demo

package me;

import com.sun.source.tree.SynchronizedTree;

public class Main  {
    public static void main(String[] args) {
        Main demo = new Main();
        //创建2个线程
        new Thread(){
            @Override
            public void run() {
               while (true){
                demo.setName("张三");
               }
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                while (true){
                    demo.setName("李四");
                }
            }
        }.start();

    }

    public  void setName(String str){
        synchronized (this){
            for ( int i=0;i

 

当然我们还可以使用lock()方法来实现同步效果

package me;

import com.sun.source.tree.SynchronizedTree;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        Main demo = new Main();
        //创建2个线程
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    demo.setName("张三");
                }
            }
        }.start();

        new Thread() {
            @Override
            public void run() {
                while (true) {
                    demo.setName("李四");
                }
            }
        }.start();

    }

    public void setName(String str) {
        lock.lock();//加锁
        try{
            for (int i = 0; i < str.length(); i++) {
                System.out.print(str.charAt(i));
            }
            System.out.println();
        }finally {
            lock.unlock();//解锁
        }
    }


}

使用lock 记得使用try 方法不然要发生异常了, 就没法解锁了 ,try 方法可以很好的处理

lock 是jdk  1.5之后出现的非常好用

 

线程死锁

有时候2个或者多个线程需要在几个共享对象上获取锁,可能会导致死锁

一般我们是使用synchronized不当的时候就是引起死锁

一个死锁的案例

    public void add(int[] a1,int[]a2){
        int value = 0;
        int size = a1.length;
        if (size == a2.length){
            synchronized (a1){
                synchronized (a2){
                    for (int i=0;i

 避免死锁

尽量避免在同一把锁的代码中用到另一把锁资源,还尽量避免使用全局对象

我们也可以使用资源排序的技术  就是A和B , B必须获得A上的锁然后才能获取B上的锁,一旦A获取A上的锁线程B 必须等待A上的锁

 

总结下线程上使用的方法

.wait() //当前线程挂起
.notify()// 唤醒正在排队等待同步资源的线程中优先级最高者结束等待
.notifyAll()//  唤醒正在排队等待资源的所有线程结束
 
Thread.sleep(); //线程休眠
Thread.yield()//暂停当前线程的执行,让具有同样优先级的线程进入可执行状态的机会
.start()  //线程开始
 
 

你可能感兴趣的:(Java,java知识回顾,Java,线程)