Java多线程学习笔记

  1. 线程概述
    (1).多线程并发实际上是人类的一种错觉,只是由于cpu运行较快,从而可以频繁的在不同任务之间相互切换,营造了一种多线程同时运行的感觉。
    (2).进程和线程:
    进程中至少有一个线程,一个线程只能从属于一个进程,而一个进程可以创建多个线程,进程之间资源不共享,但一个进程所创建的多个线程之间共享资源
    (3).对于java来说,无论多少个线程,在jvm中只共用一个方法区、一个堆,栈可以有多个。实际上,线程对象.start(),也就是创建分支栈、初始化一些资源,让该线程对象切换到就绪状态,这个过程速度很快。
    (4).java多线程调度方式为抢占式,线程对象的生命周期有:新建状态、就绪状态、运行状态、阻塞状态、死亡状态。
    (5).java的线程类型分为守护线程和用户线程,main方法就是一个用户线程
    线程的几种状态:
    多线程状态图

  2. 获取和设置线程对象名字
    (1).获取线程对象名字:
    String name = 线程对象.getName()
    默认名字为Thread-0,Thread-1
    (2).修改线程对象名字:
    线程对象.setName()

  3. 获取当前线程对象
    static Thread currentThread()
    静态方法,返回当前线程对象(返回该方法所在的线程对象)
    相比较this或者super获取线程对象,他的适用范围更广,可以在非线程对象中获取当前线程对象。

  4. 线程的sleep方法
    static sleep(long millis) throws InterruptedException
    Thread类下的一个静态方法

try {
	Thread.sleep(1000);
      }
catch(InterruptedException e){
	e.printstacktracel
}

作用:让当前线程对象进入休眠状态、进入阻塞状态,放弃占有的cpu时间片。让给其他线程使用。

睡眠中的线程的唤醒:线程对象.interuptted(),调用此方法后,sleep方法会抛出异常,从而被捕获退出睡眠
5. 线程终止的正确方式使用布尔标记

public static void main(){
	MyThread m = new MyThread();	
	Thread t = new Thread(m);
	m.run = false;
}
public class MyThread implements Runnable{
	public bool run = true;
			
	@override
	public void run(){
		if(run){
		}
		else{
			return}
	}
}
  1. yied和join线程让位和线程合并
  2. 线程不安全的条件和异步同步的概念
    一:线程不安全的条件
    1.多线程并发2.有共享数据3.共享数据有修改行为
    java中三大变量:实例变量、静态变量、局部变量(常量只读,不涉及并发安全问题)其中实例变量和静态变量是共享变量,而局部变量保存在栈中不共享,每一个栈都有属于自己的局部变量,每一个线程都有自己的栈
    二:异步就是并发,同步就是线程排队
  3. synchronized代码块
synchronized("共享对象"){
	//代码区	
}

当代码执行到synchronized的时候,无论代码块中用不用的到这个对象,程序都会停在synchronized的代码块之前,检查锁池(lockpool)中有没有这个对象的锁,如果有,拿走这个锁,在这一段代码块没有运行完之前,不会释放这个锁,也就是说锁池中(lockpool)中没有这个锁,下一个线程运行到synchronized的时候,在锁池中找不到这个锁,就会停在synchronized代码块之前,直到该锁被释放。从某种程度上说,synchronized关键字实现的功能也可以理解为一种阻塞。

由此,可以理解synchronized关键字中可以填写的内容可以有:

(1).(易理解出错)任意的字符串常量:“123”,“abc”。字符串常量存在于常量池,如果填写字符串常量,所有的线程都会停在synchronized的代码块之前排队
(2).静态变量和实例变量:无论代码块中是否用到这些变量。

  1. synchronized测试题
public class TEST {
    //1.此例在运行中,doOther方法需要等待doSome方法结束吗?不需要
    //运行doSome的时候,由于有关键字synchronized修饰,执行到doSome的时候,lockpool中mc的对象锁被拿走,但当t2运行doOther的时候
    // ,由于没有synchronized的关键字,根本不会涉及锁池的一些操作,直接执行方法,
    // 2.那么将doOther方法修改为synchronized修饰的的时候呢?会等待
    //3.创建那么再创建一个Myclass对象mc1,创建t2的时候当做参数传递呢?不会等待,synchronized加在实例方法上,一个对象一把锁
    //4.将在3的基础上,将doSome、doOther改为静态方法呢?需要,静态方法上加的锁属于类锁,无论多少对象,锁池中只有一把锁
    public static void main(String[] args) {
        MyClass mc = new MyClass();
        //MyClass mc1 = new MyClass();
        Thread t1 = new MyThread(mc);
        t1.setName("t1");
        Thread t2 = new MyThread(mc);
        //Thread t2 = new MyThread(mc1);
        t2.setName("t2");
        t1.start();
        t2.start();
    }
}
class  MyClass {

    public synchronized void doSome(){
        System.out.println("doSome begin");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("doSome over");
    }
    public  void doOther(){
        System.out.println("doOther begin");
        System.out.println("doOther over");
    }
}
class MyThread extends Thread{
    public MyClass mc;
    public MyThread(MyClass mc) {
        this.mc = mc;
    }
    @Override
    public void run() {
        if (Thread.currentThread().getName()=="t1") {


            mc.doSome();
        }
        if (Thread.currentThread().getName()=="t2"){
            mc.doOther();
        }
    }
}

11.守护线程、定时器
(1).守护线程(后台线程):一般守护线程是一个死循环,但是当用户线程结束后守护线程也不再守护,自动终止。其中具有代表性的就是jvm的垃圾回收线程。
使用方法:

Thread t = new Thread();
           t.setDaemon(true);
           t.start();

(2)定时器:使用java.util.Timer

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Test02 {
    public static void main(String[] args) throws ParseException {
        Timer t = new Timer();
        SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-HH-mm:ss");
        Date d = sdf.parse("2021-01-31-10:19");
        t.schedule(new TimeTask1(),d,1000);
//        t.schedule(new TimeTask1(),1000,1000);

    }
}
class TimeTask1 extends TimerTask{


    @Override
    public void run() {
        System.out.println("start");
    }
}

  1. 实现线程的第三种方式
    jdk8新特性:java.util.concurrent.FultureTask
    实现步骤:
    1.新建类实现callable接口
    2.实例化FultureTask对象,构造方法传入实现callable的类
    3.通过FultureTask实例对象.get()获取方法返回值,此时主线程阻塞,等待FultureTask线程执行的返回值
  2. Object的notify和wait方法(易错点)
    notify和wait方法是object对象所有,是任何一个java对象都拥有的方法。
    o.wait()方法:使正在o对象上作用的线程进入等待状态,无限期等待,并释放o对象的锁
    直到调用o.notify()唤醒,但o.notify()并不释放或者加锁
  3. 死锁的实现代码(知道怎么写才知道怎么避免)
public class lock {

    public static void main(String[] args) {
        Object o1 = new Object();
        Object o2 = new Object();
        Thread t1 = new Test1(o1,o2);
        Thread t2 = new Test2(o1,o2);
        t1.start();
        t2.start();
    }



}
class Test1 extends Thread{
    public Object o1;
    public Object o2;

    public Test1(Object o1, Object o2) {
        this.o1 = o1;
        this.o2 = o2;
    }

    @Override
    public void run() {
        synchronized (o1){
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o2){

            }

        }
    }
}
class Test2 extends Thread{
    public Object o1;
    public Object o2;

    public Test2(Object o1, Object o2) {
        this.o1 = o1;
        this.o2 = o2;
    }
    @Override
    public void run() {
        synchronized (o2){
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o1){
            }
        }
    }
}

  1. 一些常识
    synchronized的修饰实例方法的时候,一个对象一把锁,加锁的共享对象默认是this,加锁的代码块是整个方法体。
    synchronized修饰静态方法:此时为类锁,类锁不管创建了几个对象,都只有一把锁,都得等待
    一些常见的线程安全类:StringBuffer、HashTable
    非线程安全类:StringBuilder,HashSet、HashMap

  2. run方法的异常不能throws
    原因父类以及接口中的run方法没有抛出异常,原因:子类重写父类方法不能抛出更多和更宽泛的异常

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值