Java线程的三种实现方法,以及死锁

实现线程的三种方式

1.实现runable
2.继承Thread
3.重写callable接口重写call方法
   1.5后,返回一个参数

线程和进程

进程:
    占用计算机一定的cpu ,内存 ,带宽等资源的一个应用如(.exe  ,qq)
	一个操作系统包括多个进程
线程:
	qq是一个进程,会占用一定的资源
	qq同时和多个人进行聊天的时候,是相互独立的,这就是多线程
	一个进程包含多个线程

锁的两种实现

JDK 提供了两种锁:
Synchronized是一种同步锁,通过锁实现原子操作,修饰的对象有四种:(1)修饰代码块(2)修饰方法(3)修饰静态方法(4)修饰类。
另一种是LOCK,是JDK提供的代码层面的锁。

创建线程方式一:实现runable

/**
 * 方法一:实现runnable接口,并实现该接口的run()方法。
 *
 * 以下是主要步骤:
 *     ①自定义类并实现Ruannable接口,实现run()方法。
 *     ②创建Thread对象,用实现Ruannable接口的独享作为参数实例化该Thread对象。
 *     ③调用Thread的start()方法;
 */
public class MyThread implements Runnable{
    @Override
    public void run() {
        say();
    }

    //加锁的方法
    synchronized public void say(){
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName());
        }
    }
}

测试代码:

public class Runnable_Thread_Demo1 {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        Thread t1 = new Thread(myThread,"t1");
        Thread t2 = new Thread(myThread,"t2");
        t1.start();
        t2.start();
    }
}

创建线程方式二:继承Thread

/**
 * 方式二:
 *  继承Thread类,重写run方法。
 * Thread类本质上是实现了Runnable接口的一个实例
 */
public class MyThread extends Thread{
    @Override
    public void run() {
        say();
    }

    //加锁的方法
    synchronized public void say(){
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName());
        }
    }


    public MyThread() {
    }
    //new MyThread的时候传入姓名,需要用到这个方法
    public MyThread(String name) {
        super(name);
    }
}

测试代码:

public class Thread_Thread_Demo2 {
    public static void main(String[] args) {
        MyThread m1 = new MyThread();
        MyThread m2 = new MyThread();
        m1.start();
        m2.start();
//        MyThread m3 = new MyThread("m1");//这样要重写MyThread的构造方法
    }
}

创建线程方式三:重写callable接口重写call方法

import java.util.concurrent.Callable;

/**
 * 方式三:
 * 实现Callable接口,重写call方法。
 * 使用ExecutorService,Callable,Future实现带返回结果的多线程。
 *
 * 如果有这样的一个场景,需要让异步执行的线程在执行完成后返回一个值给当前的线程,
 * 当前的线程需要依赖这个值做一些其他的业务操作,这个时候就要用到如下带返回值的线程了。
 */
public class MyThread implements Callable<String> {
    @Override
    public String call() throws Exception {
        say();
        return "callable中call方法返回的值";
    }

    synchronized public void say(){
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName());
        }
    }
}

测试代码:

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * Callable接口是Java1.5开始出现的只有一个带返回值的call()方法
 *      步骤:
 *          1.ExecutorService启动线程
 *          2.实例化一个自己写的线程类
 *          3.Future接收返回的参数
 *          4.Future.get取得返回值(get方式会阻塞,需要抛出异常)
 */
public class Callable_Thread_demo3 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // ExecutorService启动线程
        ExecutorService executorService = Executors.newCachedThreadPool();
//        ExecutorService executorService1 = Executors.newSingleThreadExecutor();//多种启动方式

        // 实例化一个自己写的线程类
        MyThread m1 = new MyThread();
        MyThread m2 = new MyThread();

        // Future接收返回的参数
        Future<String> submit = executorService.submit(m1);
        Future<String> submit2 = executorService.submit(m2);

        System.out.println(submit.get());//get方式会阻塞,需要抛出异常
        System.out.println(submit2.get());

        //关闭
        executorService.shutdown();
    }
}

死锁

sleep 和 wait的区别?

1. sleep(毫秒)
   放弃CPU的执行权;
   但是不会放弃锁;
2.wait(可选)
  放弃CPU的执行权;
   但是会放弃锁;

死锁产生的条件以及解决
产生死锁必须同时满足以下四个条件,只要其中任一条件不成立,死锁就不会发生.通常破坏循环等待是最有效的方法。

互斥条件:一个资源每次只能被一个进程使用。
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系

死锁代码示例:

/**
 * 死锁测试
 * A 和 B 不能同时获得筷子和勺子
 */
public class DeadThread {
    A a = new A();//可以看做是共有的资源.
    B b = new B();

    public DeadThread() {
        a.start();
        b.start();
    }

    public static void main(String[] args) {
        new DeadThread();
    }

    //线程A
    class A extends Thread {
        @Override
        public void run() {
            getSZ();
        }

        synchronized public void getSZ() {
            System.out.println("我有勺子,我想要筷子");
            try {
                Thread.sleep(1000);
                b.getKZ();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //线程B
    class B extends Thread {
        @Override
        public void run() {
            getKZ();
        }

        public synchronized void getKZ() {
            System.out.println("我有筷子,我想要勺子");
            try {
                Thread.sleep(1000);
                a.getSZ();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

了解更多多线程

你可能感兴趣的:(Java学习)