3.多线程

Java锁
java几种锁_java中有几种锁_孤雁寒窗的博客-CSDN博客
Java锁的种类_融极的博客-CSDN博客_java 锁有几种

1.多线程概念理解

计算机中的程序(Application):

(程序==软件 ( 程序:可能包含一系列进程).exe)

进程:

计算机中解决没有顺序关系的多个任务的执行机制。

进程的优点:

独立性高(安全:每个进程都会开辟自己独有的内存);

进程的缺点:

1.创建进程耗时,2. 数据共享困难

Java应用程序(Application):

程序==jvm进程

线程:
线程是进程中创建出来的。

进程中创建出来用来解决多任务的线程 共享内存 创建线程基本不耗费资源 不安全 同步锁

  • 进程是重量级多任务解决技术;
  • 线程是轻量级多任务解决技术。

2.线程的使用

 定义:
new Thread(?),new Thread子类(?)
启动:
线程引用.start()
运行:任务
线程中的run()
加入
Thread.join()
中断
interrupt() : set interrupt status 设置中断状态,不是结束掉线程

在Java中创建线程的两种方式
继承java.lang.Thread类
实现java.lang.Runnable接口

1.代码案例:extends Thread

public class Test {
    public static void main(String[] args) {
        // 创建一个线程对象
        MyThread t1 = new MyThread();
        t1.start();
        int n = 0;
        for (int i = 0; i < 100; i++) {
            n++;
        }
        System.out.println("我是谁,我在哪里?");
    }
}

// 应该有任务
// 定义了Thread 的子类
class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println("我是第一个线程");      // 线程1:thread-1
        super.run();
    }
}

2.代码案例:implements Runnable

public class Test2 {
    public static void main(String[] args) {
        new Thread(new MyRunner()).start();     // t1
        new Thread(() -> System.out.println("第三个线程")).start();  // t2
        System.out.println("main.............");    // main
    }
}

// 定义了Runable接口的实现类
class MyRunner implements Runnable{
    @Override
    public void run() {
        System.out.println("第二个线程");
    }
}

之后这些方法就不建议使用了:
暂停
~~~~suspend()

恢复
resume()

停止
stop()

线程的工具方法 静态方法
Thread.sleep(long) 停止多长时间
Thread.yield() 让出cpu
Thread.currentThread() :

3.线程协作 同步

join()

使用 synchronied 配合 Object 下的 wait 和 notify 方法实现 线程同步
synchronied相同锁名的代码块在任何时候都只能有一个线程执行
wait等待
notify唤醒
notifyAll唤醒全部

1.代码案例:休眠,阻塞

public class Test {
    public static void main(String[] args) {
        //new T1("t1").run();
        //new Thread(new T2("t2"),"t22").start();

        Thread t2 = new Thread(new T2("t2"), "t22");
        T1 t1 = new T1("t1", t2);
        t1.start();
        t2.start();
        System.out.println("main...............");
    }
}


class T1 extends Thread{
    private Thread t2;
    public T1(String name,Thread t2) {
        super(name);
        this.t2 = t2;
    }

    @Override
    public void run() {

        for (int i = 0; i < 10; i++) {
            System.out.println(getName()+":"+i);
            if (i == 5){
                try {
                    t2.join();  // 阻塞他
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            try {
                // 休眠1秒钟
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class T2 implements Runnable{
    private String name;

    public T2(String name) {
        this.name = name;
    }

    // 因为Runnable是,里面没有name属性,所以在上面定义一个
    @Override
    public void run() {
        for (int i = 10; i > 0 ; i--) {
            System.out.println(name+":"+i);
        }
    }
}

4.守护线程

setDaemon(true): 设置守护线程

5.线程优先级

t.setPriority(10): // 设置线程优先级 1~10 优先级越高,越有机会被CPU执行

代码案例:

public class Test {
    public static void main(String[] args) {

        // 错误代码
        //Thread tt = new Thread(new T());

        Thread t = new T();
        // setDaemon : 设置守护线程
        t.setDaemon(true);
        // 设置线程优先级 1~10  优先级越高,越可能被CPU执行
        t.setPriority(10);
        System.out.println("开始前:"+t.isAlive());
        // 中断
        // 当前线程:main
        t.interrupt();      //this != currentThread()
        t.start();
        System.out.println("开始后:"+t.isAlive());
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("main..............end");
        System.out.println(t.isAlive()+"alive");
    }
}


class T extends Thread{
    @Override
    public void run() {

        {
            for (int i = 0; i < 10; i++) {
                System.out.println(i);
                System.out.println("alive"+this.isAlive());

                if (this.isInterrupted()){
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //break;
                }
                // 中断线程:当前线程
                System.out.println(Thread.currentThread().isInterrupted());     // false
                if (i == 5){
                    System.out.println("---------------");
                    System.out.println(Thread.currentThread());
                    System.out.println(this);
                    // this 和 Thread.currentThread()  不相等
                    System.out.println((this == Thread.currentThread())+"====");    // 返回:false
                    //this.interrupt();
                    Thread.currentThread();
                }
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

6.经典案例

6.1. 蒸馒头案例:使用了多线程,其中包含集合存取,锁,及子锁

// 蒸馒头案例:使用了多线程,其中包含集合存取,锁,及子锁
// 造成子锁的原因:是锁的嵌套
public class Test {

    // 采用集合存取数据,因为数据是可变的
    static List<String> data = new LinkedList<>();       // 馒头筐子
    public static void main(String[] args) {

        new Zuo("易建联").start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Chi("科比").start();
        new Chi("詹姆斯").start();
        new Chi("奥尼尔").start();
    }
}


class Zuo extends Thread{
    private String name;

    public Zuo(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        while (true) {
            // 唤醒锁"a"
            synchronized ("a") {
                for (int i = 1; i < 11; i++) {
                    System.out.println("生产第" + i + "个馒头");
                    Test.data.add("馒头" + i);
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                "a".notifyAll();
            }
            try {
                synchronized ("b"){
                    "b".wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


class Chi extends Thread{
    private String name;

    public Chi(String name) {
        this.name = name;
    }

    @Override
    public void run() {

        String s = null;
        while (true){
            // 把锁放在synchronized ()中
            synchronized ("a"){
                if (Test.data.size() == 0){
                    try {
                        System.out.println(name+"发现没有馒头~");
                        // 唤醒锁
                        synchronized ("b"){
                            "b".notify();
                        }
                        // 加一把锁
                        "a".wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            s = Test.data.remove(0);
            System.out.println(name+"吃掉了"+s);
        }
        /*try {
            System.out.println(name+"正在消化");
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
    }
}

7.线程的另一种使用方式

Executor 执行器
ExecutorService 执行器服务者

Callable 类似 Runnable

Runnable 缺点1:没有返回值,解决办法是 ,使用共享变量 加 synchronized

Runnable 缺点2:不能抛出任何异常

Callable 定义了泛型返回值,定义了声明异常

Future<Integer>

创建几个对象及存放位置

public class Test {
    public static void main(String[] args) {

        // 字符串对象是可以不用new就可以创建对象的,所以字符串对象是Java中的特殊对象。存放在串池中:不会被垃圾回收,不会重复

        // 以下代码在jvm 内存中创建了几个对象
        String ss = "aaa";      // 创建了1个对象    aaa
        String ss2 = "aaa";     // 创建了0个对象
        String sss = new String(ss);    // 创建了1个对象   new String()
        String s = new String("abc");   // 创建了2个对象  1.abc  2.new String("abc")
        String s2 = new String("aaa");  // 创建了1个对象
        System.out.println(ss == ss2);  // true
        System.out.println(ss == sss);  // false
        System.out.println(ss == s2);   // false

        // 变量或常量 + 变量或常量 等于new堆    、 常量+常量=常量  在池中
        String s3 = ss + "d";   // 创建了2个对象      "d"  abcd
        String s4 = "aaa" + "d";    // 创建了1个对象      abcd
        System.out.println(s3 == s4);   // false
        System.out.println(s3.equals(s4));      // true
        System.out.println(s3 +"----" + s4);


        // 字符串和数组是一个设计理念   字符串就是 ?数组
        // 数组的特点:数组不会改变
        String a = "a";
        a += "b";
        a += "c";
        // 变量+常量
        // 创建了5个对象

        System.out.println("-------------");
        StringBuffer sb = new StringBuffer("a");    // 创建了2个对象
        sb.append("b");     // 1
        sb.append("c");     //  1
        System.out.println(sb.toString());
        System.out.println(sb.length());
        System.out.println(sb);


    }
}

StringBuffer

StringBuffer//线程安全 但效率低
StringBuilder//线程不安全 但效率高

public class Test {
    public static void main(String[] args) {
        String line = "i     am           stdnet";
        StringBuffer temp = new StringBuffer();
        boolean flag = false;
        for (int i = 0; i < line.length(); i++) {
            char c = line.charAt(i);
            if (c == ' ' && flag){
                continue;
            }
            if (c != ' '){
                temp.append(c);
                if (flag){
                    flag = false;
                }
            }
            if (c != ' ' && !flag){
                temp.append(' ');
                flag = true;
            }
        }
        System.out.println(temp);

        //    \\s+ :正则表达式
        System.out.println(line.replaceAll("\\s+"," "));
    }
}

同步与异步

复制package com.bigdata09.day20.demo1;

import java.util.concurrent.*;

public class Test {
    static int rs = 0;
    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        new Thread(new T1()).start();
//        System.in.read();
//        int sum = rs;
//        System.out.println(sum);

        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<Integer> call = executorService.submit(new T2()); // 没有等待 异步(各做各的)
        System.out.println("线程任务已提交,等待输出结果");
        for (int i = 0;!call.isDone();i++){
            if (i > 2) {
                break;
            }
            System.out.println("等待"+(i+1));
            Thread.sleep(200);
        }
        if (call.isDone()) {
            System.out.println("这是未来结果");
        }
        /*System.out.println(call.get()+"这是未来结果"); // 同步结果*/

        System.out.println("main...........");

    }
}
class T1 implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            Test.rs+=1;
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class T2 implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i < 10; i++) {
            sum+=i;
            System.out.println(i);
           int rd = (int) (Math.random()*10); // 0~9的随机数
            System.out.println("sleep:"+(rd*10));
            Thread.sleep(40);
        }
        return sum;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值