首页 > 代码库 > 基础笔记11(线程)

基础笔记11(线程)

有如下说法(Synchronized的内存可见性)

单一线程中,只要重排序不会影响到程序的执行结果,那么就不能保证其中的操作一定按照程序写定的顺序执行,即使重排序可能会对其它线程产生明显的影响。
在Java内存模型下,每个线程都有它自己的工作内存(主要是CPU的cache或寄存器),它对变量的操作都在自己的工作内存中进行,而线程之间的通信则是通过主存和线程的工作内存之间的同步来实现的。

导致共享数据出错的两个问题:重排序;共享数据及时更新。

synchronized(M){//}的使用:
当ThreadA释放锁M时,它所写过的变量(存在它工作内存中的)都会同步到主存中,而当ThreadB在申请同一个锁M时,ThreadB的工作内存会被设置为无效,然后ThreadB会重新从主存中加载它要访问的变量到它的工作内存中(是ThreadA中修改过的最新的值)。通过这样的方式来实现ThreadA到ThreadB的线程间的通信。

  

 

1.进程和线程

进程:系统调度程序的过程。每个进程有自己内存空间

线程:在进程中程序的执行路径。cup的最小执行单位。只能cup为线程分配一些属于进程的内存空间。

2.线程创建的2种方式:继承thread或者实现runnable接口。都有重写run()方法。(thread实现了runnable接口,相当于代理runnable)

因为单继承原则,继承没有实现接口方式灵活。

3.线程第三种创建方式(并发包下)实现callable接口线程可以有返回值,可抛出异常。(简介:)

class Race implements Callable<Integer> {
    int n;
    boolean flag = true;

    @Override
    public Integer call() throws Exception {
        while (flag) {
            n += 10;
        }
        return n;
    }
ExecutorService exe = Executors.newFixedThreadPool(1);
        Race tortoise = new Race();
        // 获取返回值
        Future<Integer> submit = exe.submit(tortoise);
        Thread.sleep(300);
        //结束循环
        tortoise.flag = false;
        Integer i = submit.get();
        System.out.println(i);
        exe.shutdown();

4.线程的状态:

新生状态—就绪状态--运行状态--阻塞状态--结束状态。

新生:线程创建(new)分配内存空间。调用start()进入就绪状态。

就绪:拥有运行的条件,等待cpu的执行。处于就绪队列

运行:运行run(),运行完任务结束,或者等待其他资源阻塞状态,或者分配时间未执行完,就绪状态下次执行。

阻塞:运行时执行sleep()或者等待i/o等其他资源,释放cpu,阻塞条件结束,进入就绪状态

结束:任务结束,或者被强制结束线程(strop,destroy,会出现异常,并且不会释放锁)

注意:常用run(while(true))内添加标识外部调用(set(false))终止线程,并不能保证精准。

 

阻塞:

5.合并线程:

join();等待该线程结束。(在线程加入主线程(或者是所在外线程)位置(join()),阻塞主线程之后的执行,等该线程结束主线程再执行。

join(int t):只等待该线程t时间。

class JoinTest extends Thread {
public void run() {
        //Thread.sleep(3333);
        int i = 0;
        while (i < 11111) {
            System.out.println(i++);
        }}

public static void main(String[] args) throws InterruptedException {
JoinTest j = new JoinTest();
        j.start();
        for (int i = 0; i < 11; i++) {
            if (i == 4) {
                j.join();
            }
            System.out.println("main()" + i);
        }

输出:

...
11
main()3
..
11110
main()4
main()5
...
也可能是://并不能保证谁先执行谁后执行。只是在外线程一直执行到join()位置如果该线程未执行完外线程才阻塞,让该线程先执行完。(个人理解)
...
11110
main()2
main()3
...

6。Thread.yield():静态方法,暂停当前线程当次执行,让出cpu给其他线程,下次继续执行之后的。

i=0;
while(i<100){
i++;
if
(i == 4) { Thread.yield(); }

7.Thread.sleep(int s):不释放cpu,暂停执行。一般用于时间相关的操作(延迟/定时)

7.1。wait(),释放锁等待。notify()/notifyall()唤醒。

8.常见的方法:

        JoinTest j = new JoinTest();//已经继承Thread
        j.isAlive();//线程是是否是活得
        j.getName();//得到线程名字
        j.setName("ThreadTest");
        //优先级高并不保证先执行,只是提高执行概率。
        j.setPriority(Thread.MAX_PRIORITY);//设置优先级
        j.getPriority();//优先级
Thread currentThread = Thread.currentThread();//获取当前线程

9.同步:sychronized用于方法或者对象。

可以用于单例模式(分为懒汉和恶汉模式)

对于静态成员,一般锁定class字节码。

对于静态内部类调用其关联的静态方法时候才加载。(可以实现延迟加载的效果)

int i;
Object o =new Object();
//多线程执行下面
run(){
//每个线程执行到此,获取到对象的锁才能继续执行。
synchronized (o) {
++i;

 

并发获取值时候并没出现问题。

10.线程死锁:

 一种解决模型:生产消费(procedure co‘m

wait() notify/notifyall

11.任务调度:Timer/TimerTast,定时器,定时调度。(TimerTast 实现了runnable接口)

       Timer timer = new Timer();
       timer.schedule(TimerTask task, Date time); //执行一次
       timer.schedule(TimerTask task, long delay, long period);间隔多久重复执行

 

 

 

代理模式:

 

基础笔记11(线程)