Java线程笔记

1.方法前加上synchronize可以将方法变为同步。

2.线程调用start()的顺序不代表线程调用的顺序。

3.线程之间的数据不同享,如果要共享需要加上synchronize关键字。
MyThread myThread=new MyThread();
Thread t1=new Thread(myThread)。
Thread t2=new Thread(myThread);

4.println(i--);虽然println是同步的方法,但是i--发生在参数中,synchronize是在方法体中。

5.线程的构造方法是在main线程中,mythread.run()方法在main线程中,mythread.start()在本线程中。

6.Thread thread=new Thread(MyThread mythread);
    this.getName());//为mythread.getName();
    Thread.currentThread().getName();//为thread.getName();
7.isAlive();//测试线程是否已启动,或者还未终止。
8.sleep();//使线程休眠
9.getId();//获取线程的唯一标识
10.停止线程
stop();//废弃,不安全
suspend();//废弃,不安全
调用的方法加上了synchronized,容易造成独占的缺点。
suspend(),方法运行到println()时,使用suspend()暂停,println()的锁未释放,导致不能打印后面的println(),使得运行结果不同步。
resume();//废弃,不安全
interrupt();//推荐

11.线程中断
interrupt();
interrupted();
isInterrupted();

12.yield();//放弃当前的cpu资源,将它让给其它的任务去占用cpu执行时间。yeild()将cpu让给其他资源导致速度变慢。

13.线程的优先级。线程的优先级分为1~10个等级。
优先级的继承性:A线程启动B线程,B线程的优先级与A线程是一样的。
优先级的规则性:高优先级的线程大部分先执行完。
优先级的随机性:优先级高的线程不一定先执行完。

14.守护线程。
Java中有两种线程,一种是用户线程,另一种是守护线程。
任何一个守护线程都是JVM中所有非守护线程的“保姆”,只要当前JVM中存在任何一个非守护线程没有结束,守护线程就在工作。
只有当最后一个非守护线程结束时,守护线程才随着JVM一同结束工作。

15.两个Thread同时操作一个对象,对象只有一个实例变量,出现变量覆盖,在方法前加上synchronized。

16.只用共享的资源才需要同步化,需要加上synchronized。

17.A线程持有object的锁,B线程可以以异步方式调用object的非synchronized方法。

18.A线程调用了object的synchronized的X方法(非static),相当于A线程获得了对象object的锁,B线程可以调用Object的非synchronized方法,但是想要调用synchronized方法,必须等A线程完成X方法。

19.synchronized拥有锁重入的功能。加了synchronized的方法可以调用本类中加了synchronized的方法。
子类的synchronized方法可以调用父类的synchronized方法。
当同步synchronized方法发生异常,同步锁会释放。
子类重写父类的synchronized方法,需要在子类的方法前加上synchronized才能使子类的方法同步。

20.synchronized同步语句块。
使用同步代码块synchronized(this){}来代替同步方法synchronized method()。
不在synchronized块中的就是异步执行,在synchronized块中的就是同步执行。
线程A调用了Object的synchronized(this)代码块,线程B想要调用Object的其它synchronized(this)代码块或者是synchronized方法,必须等线程A执行结束后才能调用。

21.将任意对象作为对象监视器
1)synchronized(非this对象){},一般是实例变量及方法的参数。
2)synchronized(非this对象){}与synchronized(this){}或者是synchronized方法是异步的。
    synchronized(this){}不能加在静态方法里面。
3)synchronized(非this对象){},非this对象必须为同一个对象,方法才是同步的,如果是不同的对象,仍然为异步。
4)synchronized持有不同对象监视器是异步的。

22.synchronized(非this对象x){};
1)多个线程同时执行synchronized(非this对象x){},同步代码呈现同步效果。当其它线程执行x对象中synchronized同步方法呈现同步效果。如果使用不同的x对象,则为异步。
2)其它线程执行x对象中的synchronized方法时,为同步。
3)其它线程执行x对象中的synchronized(this){}时,为同步。

23.synchronized加在static静态方法上是给Class类上锁,加在非static静态方法上是给对象上锁。
synchronized加在static静态方法前的效果等价于synchronized(xx.Class){}
synchronized加在非静态方法前的效果等价于synchronized(this){}

24.synchronized(str);//给String类型上锁时,如果String值一样,则会导致公用同一把锁,导致同步。

25.在将任何数据类型作为同步锁时,需要注意是否有多个线程同时持有锁对象,如果同时持有,则这些线程是同步的;如果分别获得锁对象,则这些线程就是异步的。
只要对象不变,即使对象的属性改变,还是同步。


26.volatile关键字,主要作用是使变量在多个线程可见,就是强制从公共堆栈中取值。
启动线程时,线程中的变量会存在于公共堆栈和私有堆栈中,私有堆栈和公共堆栈是不同步的。JVM为-server模式,线程一直在私有堆栈中取值。mian函数中,即使改变了线程中变量的值,改变的也只是公共堆栈中的值,并没有改变私有堆栈中的值。
使用场合,多个线程中可以感知实例变量被改变,可以获得最新的值。

27.volatile和synchronized的比较
1)volatile的性能比synchronized性能更好。
2)volatile只用于修饰变量,synchronized用于修饰方法,代码块。
3)多线程访问volatile不会发生阻塞,而访问synchronized会发生阻塞。
4)volatile可以保证数据的可见性,不能保证数据的原子性;而synchronized可以保证原子性,从而间接保证可见性,synchronized会将私有内存和公共内存中的数据同步。
5)volatile解决的是变量在多个线程之间的可见性;synchronized解决的是线程访问资源的同步性。
线程安全包含原子性和可见性两个方面,Java的同步机制都是围绕这两个方面来确保线程安全的。

28.查看jvm是否发生死锁
cd C:\Program Files\Java\jdk1.8.0_121\bin
jps
jstack -l id

29.synchronized的两个特性:互斥性和可见性。
synchronized可以解决一个线程看到对象处于不一致的状态,还可以保证进入同步方法或者同步代码块的每个线程,都看到由同一个锁保护之前所有的修改效果。

30.线程的等待/通知机制。
wait();//使处于临界区的线程进入等待状态,释放被synchronized线程同步的锁。
notify();//随机唤醒一个因调用wait()操作而处于阻塞状态中的线程,使其进入就绪状态。如果没有处于阻塞状态的线程,方法被忽略。仅通知一个线程。
notifyAll();//使所有正在等待队列中等待同一共享资源的”全部“线程从等待状态退出,进入可运行状态。此时,优先级最高的线程优先执行,也可能随机执行。
等待/通知机制的实现。
1)需要先调用wait()方法,才能调用notify()方法。notify()方法执行后不会立即释放锁。

31.线程状态切换

32.方法notify()执行后,不释放锁,必须执行完notify()方法所在的同步synchronized()所在的代码块才会释放锁。

33.当线程是wait()状态,调用interrupt()方法会报错。

34.总结
1)执行完同步代码块就会释放对象的锁。
2)执行同步代码块时,遇到异常,锁也会被释放。
3)执行了锁所属对象的wait()方法,这个线程会释放对象锁,此线程会进入线程等待池,等待被唤醒。

35.wait(long timeout)在timeout毫秒之后会被唤醒,或者可以调用notify唤醒。

36.通过管道进行线程之间的通信:字节流。
pipeStream:一个线程发送数据到输出管道,另一个线程从输入管道中心读取数据。

37.join()方法。
作用:阻塞当前线程,当当前线程中调用子线程的run()方法结束,子线程销毁,接着执行当前线程。
join与synchronized区别:
1)join是在内部使用wait()方法进行等待。
2)synchronized则是使用”对象监视器“原理作为同步。

38.join()方法和interrupt()方法如果彼此遇到,会出现异常。

39.join(long timeout)和sleep区别,join()内部是使用wait()方法实现,锁会被释放。

40.类ThreadLocal
类ThreadLocal解决的是变量在不同线程间的隔离性,也就是不同线程拥有自己的值,不同线程的值可以放入ThreadLocal类中进行保存。
ThreadLocal首次get()值为null,可以在initialValue()中设置初始值。
InheritableThreadLocal类继承可以继承父线程中的值,需要重写childValue(Object parentValue)方法。

41.使用ReentrantLock类实现同步。lock()上锁,unlock()解锁。是对对象的监视器。

42.使用ReentrantLock类和Condition实现等待/通知。
使用condition.await()使线程进入等待状态。
使用condition.signal();和condition.signalAll();实现通知。、

43.Object类与Condition类   类比
wait()  <==>  await()
wait(long timeout)  <==>  await(long timeout)
notify()  <==>  signal()
notifyAll()  <==>  signalAll()

44.公平锁和非公平锁
公平锁:线程获取锁的顺序是按照线程加锁的顺序来分配的,先来先得。
非公平锁:随机获得锁,可能会造成某些线程一直拿不到锁。
ReentrantLock lock=new ReentrantLock(fair);

45.getHoldCount();返回当前线程调用lock()方法的次数。

46.getQueueLength();返回正等待获取此锁定的线程估计数。

47.ReentrantReadWriteLock类
ReentrantLock具有完全互斥排他的效果,即同一时间只有一个线程在执行ReentrantLock.lock()方法后面的任务。虽然保证安全,但是效率低。
ReentrantReadWriteLock类可以加快运行效率。
读操作相关锁:共享锁。
写操作相关锁:排他锁。
多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。
ReentrantReadWriteLock().readLock().lock();
ReentrantReadWriteLock().readLock().unlock();

ReentrantReadWriteLock().writeLock().lock();
ReentrantReadWriteLock().writeLock().unlock();

48.定时器的使用
Timer()类是设置计划任务,封装任务的类是TimerTask()。执行计划任务的代码需要放入TimerTask的子类中。
    private static Timer timer=new Timer();
    static public class MyTask extends TimerTask {
        @Override
        public void run() {
            System.out.println("运行了!时间为:"+new Date());
        }
    }
    //执行
    timer.schedule(task,dateRef);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章