java多线程
来源:互联网 发布:mysql 5.5.37 for mac 编辑:程序博客网 时间:2024/06/07 12:15
线程的创建方式有两种
继承Thread类
public class ThreadTest extends Thread{public void run(){for(int i = 0;i < 10;i++)System.out.println(i);}public static void main(String[] args) {new ThreadTest().start();}}
重写run()即可。
Thread类有如下几个常用的方法:
public static void yield() //暂停当前正在执行的线程对象,并执行其他线程
public static void sleep(long millis) //在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权。public void interrupt() //中断线程public static boolean interrupted() //测试当前线程是否已经中断public boolean isInterrupted() //测试线程是否已经中断public final boolean isAlive() //测试线程是否处于活动状态public final void setPriority(int newPriority) //更改线程的优先级public final void setName(String name) //改变线程名称,使之与参数name
相同public final void join() //等待该线程终止public final void setDaemon(boolean on) //将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出public void setContextClassLoader(ClassLoader cl) //设置该线程的上下文 ClassLoaderpublic static void yield() //暂停当前正在执行的线程对象,并执行其他线程
实现Runnable接口
public class RunnableTest implements Runnable{private int count;private int num;public RunnableTest(int i,int num){count = i;this.num = num;}public void run(){for(int i = 0;i < count;i++)System.out.println("num"+num+":"+i);}public static void main(String[] args) {Runnable r1 = new RunnableTest(10,1);Runnable r2 = new RunnableTest(20,2);new Thread(r1).start();new Thread(r2).start();}}
创建两个任务,通过Thread类执行任务。
线程的创建需要一定的代价,所以当需要执行多个任务时,创建同样多的线程是不可取的。这时可以使用线程池创建一定数量的线程,同一个线程在执行完一个任务后可以去执行另外的任务,也就是线程的重复利用。如:
public static void main(String[] args) {/*Runnable r1 = new RunnableTest(10,1);Runnable r2 = new RunnableTest(20,2);new Thread(r1).start();new Thread(r2).start();*/ExecutorService es = Executors.newFixedThreadPool(10);for(int i = 0;i < 100;i++){es.execute(new RunnableTest(i*3,i));}es.shutdown();}
创建10个线程用于执行100个任务。
其中,Executors类提供了一些静态方法用于获取各种类型的线程池。相关信息可以查帮助文档。
线程同步
当多个线程需要访问相同的资源(如变量,java对象)时,就涉及到了线程之间的同步问题。在java中,线程同步使用synchronized关键字即可。当然,也可以通过Lock接口显示的加锁。
如果给一个实例方法(类方法)声明为synchronized,那么当一个线程访问这个方法时会隐式地给对象加锁,其他线程访问这个对象(类)的同步方法时就会被阻塞(访问非同步方法不会阻塞)。
如果是同步块,那么一个线程访问同步块所在的方法时,不会阻塞其他线程对其他同步方法,而只是阻塞所同步的对象的访问,即synchronized(Object o)里面的o对象。
如果是显示地加锁,那么先通过new ReentrantLock()获得一把锁,然后在需要同步的代码调用其lock()和unlock()即可。
另外,通过Lock接口的newCondition()获得一个Condition类,其中的await(),signal(),signelAll()可以实现线程间的协作。请看下面一个经典例子:
package multi_thread;import java.util.LinkedList;import java.util.Random;import java.util.Vector;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ProductorConsumerTest {private static Buffer buf = new Buffer(30);private static Random rand = new Random();public static void main(String[] args) {ExecutorService es = Executors.newFixedThreadPool(6);for(int i = 0;i < 3;i++){es.execute(new Product(i));}for(int i = 0;i < 3;i++){es.execute(new Consumer(i));}es.shutdown();}static class Product implements Runnable{private int num;public Product(int num){this.num = num;}public void run(){while(true){int i = rand.nextInt(15);//System.out.println("product "+num+":"+i);buf.setn(i);try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}static class Consumer implements Runnable{private int num;public Consumer(int num){this.num = num;}public void run(){while(true){int i = rand.nextInt(15);//System.out.println("consumer "+num+":"+i);buf.getn(i);try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}class Buffer{private static int count = 0;private LinkedList<Integer> buf = new LinkedList<Integer>();private int size = 0;private Lock lock = new ReentrantLock();private Condition empty = lock.newCondition();private Condition full = lock.newCondition();public Buffer(int size){this.size = size;}public void setn(int n){lock.lock();while(buf.size()+n > size){System.out.println("buf.size():"+buf.size()+";setn("+n+")...please wait");try {full.await();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}for(int i = 0;i < n;i++){buf.add(count++);}System.out.println("buf.size():"+buf.size()+";setn("+n+")");empty.signal();lock.unlock();}public void getn(int n){lock.lock();while(buf.size()-n < 0){System.out.println("buf.size():"+buf.size()+";getn("+n+")...please wait");try {empty.await();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}for(int i = 0;i < n;i++){buf.remove(0);}System.out.println("buf.size():"+buf.size()+";getn("+n+")");full.signal();lock.unlock();}}
用Lock和Condition完成生产者消费者的问题。
另外附上两个并发编程的例子吧。
i++
首先要说明的是,在java中i++操作不是原子操作,这就意味着如果i是多线程共享的,那么i++操作就不是线程安全的。
那么,可以使用java提供的原子类来解决问题。在java.util.concurrent.atomic包中有AtomicLong,AtomicInteger等类提供线程安全的操作。
不安全的单例类
public class Singleton {private static Singleton single = null;private Singleton(){}public static Singleton getInstance(){if(single == null){single = new Singleton();}return single;}}
当两个线程同时访问getInstance()时,可能一个线程判断single为null,然后执行new Singleton(),而同时另一个线程在它还没创建完成时也判断single是否为null,这是两个线程就都创建了一个Singleton实例了,显然这是不符合单例模式的初衷的。
- 【Java多线程】多线程死锁
- Java 多线程
- java 多线程
- java多线程
- JAVA多线程
- java多线程
- JAVA多线程
- java多线程
- JAVA 多线程
- Java多线程
- java多线程
- JAVA 多线程
- Java 多线程
- Java 多线程
- java多线程
- Java 多线程
- Java多线程
- java 多线程
- POJ 1047——解题报告
- vs如何向main函数传参数、设置字符编码、设置OpenMp等
- 使用lint提高android代码质量
- 算法——动态规划篇——最长公共子序列
- 九度 题目1366:栈的压入、弹出序列
- java多线程
- 用maven导出依赖jar
- ios上ZXing库的配置流程
- pool is already maxed out. [managed: 15; max: 15]
- NetBeans 7.2 or 8.0 编辑文件时不显示文件路径。
- 如何制作Cognos Mobile上面Active Report
- json_decode 转换json对象为数组需注意true 你加了吗?
- linux 高级命令- -
- 速算24点(搜索)