Java / Android 多线程和 synchroized 锁

s

AsyncTask 在Android R中标注了废弃 

synchronized 同步

Thread:

thread.start()

 public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

    private native void start0();

start0 是个native方法

进程和线程 进程> 线程

进程= 操作系统独立区域 ,可以有多条线程

进程和线程可以进行并行工作,线程依赖进程

Runable: 接口 重写run

new Thread(runnable)

thread.start(runnable)  runnable在Thread内部标为target

相比于thread,runnable可以重用 : Thread1(runnable),Thread2(runnable)

ThreadFactory: Thread 工厂方法
  private static void threadFactory() {
        AtomicInteger count = new AtomicInteger(0);
        ThreadFactory factory = new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r,"Thread-"+count.incrementAndGet());
            }
        };
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        };

        Thread thread = factory.newThread(runnable);
        thread.start();

        Thread thread1 = factory.newThread(runnable);
        thread1.start();
    }

Executor: 接口

   private static void executor() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable run");
            }
        };
        Executor executor = Executors.newCachedThreadPool();
        executor.execute(runnable);
        executor.execute(runnable);
        executor.execute(runnable);
    }
public interface Executor {

    /**
     * Executes the given command at some time in the future.  The command
     * may execute in a new thread, in a pooled thread, or in the calling
     * thread, at the discretion of the {@code Executor} implementation.
     *
     * @param command the runnable task
     * @throws RejectedExecutionException if this task cannot be
     * accepted for execution
     * @throws NullPointerException if command is null
     */
    void execute(Runnable command);
}

newCachedThreadPool 返回 ExecutorService

void shutdown(); //关闭任务
List<Runnable> shutdownNow();//立即关闭 但是会调用intrat 用这个是安全的

  public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

内部创建线程池,和连接池一样. 包含了线程的创建 销毁等操作 (0 //默认大小,当超过最大值Integer.MAX_VALUE,就会销毁到默认大小)

60L, TimeUnit.SECONDS,线程等待回收时间
 new SynchronousQueue<Runnable>() 创建队列

Executor executor1 = Executors.newSingleThreadExecutor();创建1个线程
   public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
  public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

newFixedThreadPool 创建固定数量的线程,不推荐,如果用得少或者不用也会是这么多,而且不可扩展更多,用来处理多个集中任务

newScheduledThreadPool:可以添加延迟
  public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
Callable:有返回值的Runnable ,方法 call : Type

  private static void callable() {
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "666";
            }
        };
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<String> future = executorService.submit(callable); //后台任务Future 否则就会阻塞主线程  execure则会阻塞进行等待
        try {
            String result = future.get(); //阻塞进行取值,
            System.out.println(result);
        } catch (ExecutionException | InterruptedException e) {
            throw new RuntimeException(e);
        }

    }

  if (future.isDone()){
            //如果完成任务
        }

流程图

线程同步:

public class SynchronizedDemo1 implements TestDemo{
    private boolean running =true;
    private void stop(){
        running = false;
    }

    @Override
    public void runTest() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                int round = 1;
                while (running){

                }
            }
        }).start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        stop();
    }
}

看出会等待1秒然后跳出循环,但是实际上会一直执行 

每个线程都有一块独立的区域,会把变量copy,然后改变值,然后再传回去

但是如果是多线程,copy同一个值,进行修改,数据会乱

可以使用 volatile ,改变其内存可见性,同步

多线程中如若用

x++; 则会进行两步 1 int temp = x+1, 2  x = temp 不是原子操作

需要使用 synchronized 有线程调用则其他线程等待

private synchronized void count(){
    x++; 
}

AtomicInteger = int 的包装 增加原子性和同步性

AtomicInteger count = new AtomicInteger(0); //int
   AtomicInteger count = new AtomicInteger(0); //int
        ThreadFactory factory = new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r,"Thread-"+count.incrementAndGet()); //++count
               // count.getAndIncrement() //count++
            }
        };
AtomicBoolean
    private AtomicBoolean running = new AtomicBoolean(true);
         running.set(false);
            running.get()

除此之外还有

//同一个类如果有多个synchronized 一般就是有一个监视器 monitor 进行控制,只能由一个线程调用

可以再方法内部加上

synchronized (this){用当前监视器

}

synchronized在方法上会同步锁多个方法,仅供当前线程调用

public class SynchronizedDemo3 implements TestDemo{

    private int x= 0;
    private int y = 0;
    private String name;
    private Object monitor1 = new Object();
    private Object monitor2 = new Object();
    private synchronized void count(int newValue){
       synchronized (monitor1){
           x = newValue;
           y = newValue;
       }
    }

    private void  minus(int delta){
        synchronized (monitor1){
            x -= delta;
            y -= delta;
        }

    }

    //synchronized 锁住当前方法
    private synchronized void setName(String name){
        synchronized (monitor2){
            this.name = name;
        }

    }


    @Override
    public void runTest() {

    }
}

synchronized 在方法上等同于在内部的 synchronized (this)

synchronized 作用 = 同步性,互斥

死锁:多线程中,当前线程持有的锁,但拿不到需要进行执行代码中的锁,会一直等待

乐观锁 写入时先读取, 悲观锁 -读之前加锁,写入前加锁, 主要用于数据库

static 修饰的方法 用synchronized在方法上 等同于 在方法内部( synchronized (name.class))

用当前类当做锁

单例模式双重检查锁 写法1

ReentrantLock 可重入锁 需要手动加解锁,同时也要注意是否能够正常解锁

可以使用读写锁

 private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    Lock readLock = lock.readLock();
    Lock writeLock = lock.writeLock();

线程安全本质是多个线程访问共同资源,在写入时,其他线程干预了,导致数据错误

锁机制是:对资源进行访问的一种限制

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值