Java多线程碎碎念
2016-01-04 12:25
375 查看
创建线程的几种方法
实现多线程的几种方式
线程之间同步
为什么要同步
同步有哪些策略
synchronized
Lock
线程的一些方法介绍和object的wait notify
“你知道创建线程有几种方法吗?”
继承Thread
实现Runnable
实现Callable接口,通过FuctureTask 类实现有返回值的线程
Executors有几个静态函数用来构造各种线程池
submit就是把 Runnable Callable 添加到线程池中等待执行,其返回值是Future对象,同样用于获取将来的返回值
上面是线程池,Java 7 还有一个用于多核计算,分割大任务,多线程计算之后,再合并计算结果的框架 Fork/Join框架,下次再写 (其实是还没吃透 ~逃 )
上图为Java 内存模型 对一个主存里面的对象操作其实是先把这个对象复制到本地内存然后读写之后更新到主存里面,这样就导致了如果线程调度打断了更新那么就会导致出现错误,所以需要同步,同步就是然某些操作只可能被一个线程执行,也就是虽不存在多个线程执行同一个操作
释放锁的情况
同步块执行完毕
同步块遇到了wait()
不会释放的情况
遇到sleep,yeild
suspend挂起线程
明天再写,碎觉~
我来更新啦
我们发现读和读之间也变成互斥的了
这个时候如果采用Lock就会很方便的实现读与读之间的不互斥关系
通过读写锁就可以很方便的控制互斥与费互斥,另外还有很多的Lock子类供我们使用,参见api
这个方法的作用是
作用就是主线程MainThread等待threadA线程执行完毕再往下执行
yield
这个方法是调用者的线程放弃占用CPU,也就是释放CPU,然后大家再一起竞争CPU的使用权. 这个方法不会释放锁
sleep
这个方法是释放CPU一段时间,但是注意这个方法不会释放锁
wait
这个方法是Object中的方法,它的作用是使得当前这个线程进入等待状态,一直等待下去(ps : 可以使用带参数的重载函数起设定一个超时等待期限),直到有其他线程调用了notify系列函数 这个方法释放锁
notify
这一系列的函数用来使得进入等待状态的线程重新正常工作
实现多线程的几种方式
线程之间同步
为什么要同步
同步有哪些策略
synchronized
Lock
线程的一些方法介绍和object的wait notify
创建线程的几种方法
“你知道茴字有几种写法吗?”孔乙己笑着说道.“你知道创建线程有几种方法吗?”
继承Thread
------------MThread.java---------------- class MThread extends Thread { @Override public void run() { //自己的代码逻辑 } } -------------main函数-------------------- Thread t = new MThread(); t.start();
实现Runnable
------------MRunnable.java---------------- class MRunnable implements Runnable { @Override public void run() { //自己的代码逻辑 } } -------------main函数-------------------- Thread t = new Thread(new mRunnable()); t.start();
实现Callable接口,通过FuctureTask 类实现有返回值的线程
-----------------CallbackImpl------------- class CallableImp implements Callable<Integer> { private boolean isInterrupt = false; @Override public Integer call() throws Exception { while (!isInterrupt) { System.out.println(" call call"); Thread.sleep(1000); isInterrupt = true; } return new Integer(13); } } ---------------------main.java-------------------- CallableImp call = new CallableImp("AAA"); //FutureTask是Future接口的实现类,它的作用是获取Callable的返回值 FutureTask<Integer> task = new FutureTask<>(call); Thread thread = new Thread(task); thread.start(); //获取返回值,这个方法一直等待线程结束,然后把返回值返回 //另外还有一个重载的函数,提供了超时退出等待的时间参数 // get(long timeout, TimeUnit unit) Integer res = task.get(); System.out.println(res);
实现多线程的几种方式
多线程很简单,new 多个线程就OK.简单直接,但是也很粗暴.这种方式不便于管理,而且线程的创建是需要很多资源的.我们自然而然想到,多线程的目的是为了获得计算能力,如果我们的线程使用完之后不会被释放,可以回收再利用,那该多方便CallableImp call1 = new CallableImp("callable___1"); CallableImp call2 = new CallableImp("callable___2"); CallableImp call3 = new CallableImp("callable___3"); CallableImp call4 = new CallableImp("callable___4"); ExecutorService e = Executors.newFixedThreadPool(4); e.submit(call1); e.submit(call2); e.submit(call3); e.submit(call4); Thread.sleep(5000); //执行完毕之后关闭 //如果想粗暴的关闭 //使用shutdownNow() e.shutdown();
Executors有几个静态函数用来构造各种线程池
submit就是把 Runnable Callable 添加到线程池中等待执行,其返回值是Future对象,同样用于获取将来的返回值
上面是线程池,Java 7 还有一个用于多核计算,分割大任务,多线程计算之后,再合并计算结果的框架 Fork/Join框架,下次再写 (其实是还没吃透 ~逃 )
线程之间同步
为什么要同步(java线程内存模型),也就是说多线程不同步回引发什么问题(银行取钱案例)为什么要同步?
上图为Java 内存模型 对一个主存里面的对象操作其实是先把这个对象复制到本地内存然后读写之后更新到主存里面,这样就导致了如果线程调度打断了更新那么就会导致出现错误,所以需要同步,同步就是然某些操作只可能被一个线程执行,也就是虽不存在多个线程执行同一个操作
同步有哪些策略?
synchronized
synchronized可以修饰方法,也可以修饰块//括号里的参数是你想获得的哪个对象的锁参数就是那个对象 synchronized(this) { //对某一个共享对象的操作 } //同步方法是锁的目标是this public synchronized void function() { }
释放锁的情况
同步块执行完毕
同步块遇到了wait()
不会释放的情况
遇到sleep,yeild
suspend挂起线程
明天再写,碎觉~
我来更新啦
Lock
因为synchronized是有局限性的,例如我们需要在多个线程里面对一个共享数据执行些操作和读操作,自然想到应该线程之间的读和写不能同时进行,写和写也不能,但是读和读之间应该是可以同时进行的.那么我们用synchronized应该怎么实现呢-----------Data.java-------------- class Data { private String data = null; public Data(String data) { this.data = data; } public synchronized void setData(String newData) { System.out.println(this.getName()+"写入数据= " + newData); try { Thread.sleep(10); }catch(){ } data = newData; } public synchronized String getData() { System.out.println(this.getName()+"读取数据= "+data); try { Thread.sleep(10); }catch(){ } return data; } } ------------MThread.java----------------- class MThread { private Data d= null; public MThread(Data d) { this.d = d; } @Override public void run() { String data = d.get(); d.setData(this.getName()+"设置数据"); } } -------------main-------------- Data d = new Data("默认数据"); new MThread(d).start(); new MThread(d).start(); new MThread(d).start();
我们发现读和读之间也变成互斥的了
这个时候如果采用Lock就会很方便的实现读与读之间的不互斥关系
-----------Data.java-------------- class Data { private ReadWriteLock lock = new ReentrantReadWriteLock(); private String data = null; public Data(String data) { this.data = data; } public void setData(String newData) { lock.writeLock().lock(); try { System.out.println(this.getName()+"写入数据= " + newData); try { Thread.sleep(10); }catch(){} data = newData; } finally{ lock.writeLock().unlock(); } } public String getData() { lock.readLock().lock(); try { System.out.println(this.getName()+"读取数据= "+data); try { Thread.sleep(10); }catch(){ } return data; } finally { lock.readLock().unlock(); } } }
通过读写锁就可以很方便的控制互斥与费互斥,另外还有很多的Lock子类供我们使用,参见api
线程的一些方法介绍和object的wait notify
join这个方法的作用是
-----当前在主线程MainThread中------ threadA.join();
作用就是主线程MainThread等待threadA线程执行完毕再往下执行
yield
这个方法是调用者的线程放弃占用CPU,也就是释放CPU,然后大家再一起竞争CPU的使用权. 这个方法不会释放锁
sleep
这个方法是释放CPU一段时间,但是注意这个方法不会释放锁
wait
这个方法是Object中的方法,它的作用是使得当前这个线程进入等待状态,一直等待下去(ps : 可以使用带参数的重载函数起设定一个超时等待期限),直到有其他线程调用了notify系列函数 这个方法释放锁
notify
这一系列的函数用来使得进入等待状态的线程重新正常工作
相关文章推荐
- Python3写爬虫(四)多线程实现数据爬取
- C#实现多线程的同步方法实例分析
- C#线程间不能调用剪切板的解决方法
- 浅谈chuck-lua中的多线程
- C#简单多线程同步和优先权用法实例
- C#多线程学习之(四)使用线程池进行多线程的自动管理
- C#多线程编程中的锁系统(三)
- C#线程同步的三类情景分析
- C#获取进程或线程相关信息的方法
- C#停止线程的方法
- C#子线程更新UI控件的方法实例总结
- C#多线程学习之(六)互斥对象用法实例
- C#线程队列用法实例分析
- 基于一个应用程序多线程误用的分析详解
- C#多线程学习之(三)生产者和消费者用法分析
- C#多线程学习之(一)多线程的相关概念分析
- C#多线程之Thread中Thread.IsAlive属性用法分析
- 分享我在工作中遇到的多线程下导致RCW无法释放的问题
- C#多线程编程之使用ReaderWriterLock类实现多用户读与单用户写同步的方法
- C#控制台下测试多线程的方法