《Java高并发程序设计》读书笔记(第二章)

Java并行程序基础

进程:是计算机中的程序关于某数据集合的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础,进程是线程的容器,进程是程序的实体。进程中可以容纳若干个线程。
线程:是轻量级的进程,是程序执行的最小单位,使用多线程而不使用多进程进行并发程序的设计,是因为线程的切换和调度成本远小于进程。
线程的所有状态在Thread中的State枚举中定义:

public enum State{
	NEW,//线程刚刚创建 还没开始执行,等到start()方法调用时开始执行
	RUNNABLE,//程序执行状态,程序所需一切资源已经准备好
	BLOCKED,//执行过程中遇到了synchronized同步块就会阻塞,此时会暂停执行,直到获得请求的锁
	WAITING,//无时间限制的等待
	TIMED_WAITING,//等待一些特殊事件
	TERMINATED;//结束
}

初始线程:线程的基本操作

1.新建线程

1.继承Thread,重载run()方法定义线程
2.实现Runnable接口

2.终止线程

Thread.stop()会直接终止线程,并立即释放这个线程所持有的锁,若有的锁用来维持对象一致性,那么会导致数据不一致情况出现。
所以需要自定义标记变量判断线程是否需要退出。

3.线程中断

线程中断不会使线程立马退出,而是给线程发送一个通知,告知目标线程有请求需要它退出,至于如何处理由目标线程决定。

public void Thrad.interrupt();//中断线程
public boolean Thread.isInterrupted();//判断是否被中断
public static boolean Thread.interrupted();//判断是否被中断并清除当前中断状态

Thread.sleep()让当前线程休眠若干时间,会抛出InterruptedException中断一次。由于中断而抛出异常,此时会清除中断标记,如果此时不加处理,下一次循环开始时就无法捕获这个异常,需要在异常处理中再此设置中断标志位。不会释放锁资源

4.等待(wait)和通知(notify)

都是Object类的方法。
wait():一个对象调用后会停止继续执行,转为等待状态。等到其他线程调用了notify()方法为止。他必须在synchronzied语句中,会释放锁
一个线程调用了obj.wait()后,它就会进入obj对象的等待队列,这个等待队列可能有多个线程,因为系统运行多个线程同时等待某一个对象,当调用obj.notify()时,会从等待队列中随机唤醒一个线程。
notify()/notifyAll():随机唤醒一个或全部线程。
无论wait或notify方法,都需要首先获得目标对象的一个监视器,wait执行完后会释放这个监视器。

5.挂起(suspend)和继续执行(resume)线程

被挂起的线程必须等到resume()操作后才能继续执行。
suspend()不会释放任何锁资源

6.等待线程结束(join)和谦让(yield)

join():一直阻塞当前线程知道目标线程执行完毕
join()的本质是wait()实现的,所以也会释放锁
yield():一旦执行,它会使当前线程让出CPU

线程组

线程较多时,线程功能分配比较明确,就可以将相同功能的线程放在一个线程组里。

ThreadGroup tg=new ThreadGroup("PrintGroup");
Thread t1=new Thread(tg,new ThreadGroupName(),"T1");
Thread t2=new Thread(tg,new ThreadGroupName(),"T2");
t1.start();
t2.start();
System.out.println(tg.activeCount());//获得活动线程的总数
tg,list();//打印这个线程组的所有线程信息

守护线程( Daemon )

 public static class DaemonT extends Thread{
        public void run()
        {
            while(true)
            {
                System.out.println("I am alive");
                try{
                    Thread.sleep(1000);
                }catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String [] args) throws InterruptedException {
        Thread t=new DaemonT();
        t.setDaemon(true);//设置守护线程必须在线程start()之前
        t.start();
        Thread.sleep(2000);//方法中只有主线程main是用户线程 在main线程休眠2秒后退出
    }

线程优先级

t.setPriority(Thread.MAX_PRIORITY);

线程安全与synchronized

volatile只能保证一个线程修改数据后其他线程能够看到这个改动,但两个线程同时操作一个数据就会产生冲突。
synchronized的作用是实现线程间的同步,对同步的代码加锁,使得每次只有一个线程进入同步块,从而保证线程间的安全。可以保证线程间的可见性和有序性
synchronized用法:
指定加锁对象:给指定对象加锁,进入同步代码前需要获得给定对象的锁
直接作用于实例方法:相当于对当前实例加锁,进入同步代码前需要获得当前实例的锁
直接作用于静态方法:相当于对当前类加锁,进入前要获得类的锁

隐蔽性的错误

1.并发下的ArrayList
在扩容过程中,内部一致性遭到破坏,由于没有锁的保护,导致另一个线程访问到不一致的内部状态,出现越界问题。
多线程访问冲突,两个线程同时对ArrayList中的同一位置进行赋值,可用Vector替代即可解决。
2.并发下的HashMap
链表结构遭到破坏变成环了。

i++的本质是创建一个新的Integer对象,并将他的引用赋值给i。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值