Java 多线程基础
(转载请标明出处)
一、
public class FirstThread extends Thread { private int i; public void run(){ for (int i = 0; i < 100; i++) { System.out.println(getName()+" "+i); } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+" "+i); if(i==20){ new FirstThread().start(); new FirstThread().start(); } } } }
public class SecondThread implements Runnable { private int i; public void run(){ for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+" "+i); } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+" "+i); if(i==20){ SecondThread st = new SecondThread(); //通过new Thread(target , name)方法创建新线程 new Thread(st,"新线程1").start(); new Thread(st,"新线程2").start(); } } } }
ExecutorService es = Executors.newFixedThreadPool(2); Future<Integer> f1 = es.submit(newMyCallable(10)); Future<Integer> f2 = es.submit(new MyCallable(20)); System.out.println(f1.get()+" "+ f2.get()); es.shutdown();
FutureTask<Integer> ft = new FutureTask<Integer>(new MyCallable(10)); FutureTask<Integer> ft2 = new FutureTask<Integer>(new MyCallable(20)); new Thread(ft,"我是线程1").start(); new Thread(ft2,"我是线程2").start(); System.out.println(ft.get());
public class ThirdThread { public static void main(String[] args){ //创建Callable对象 ThirdThread rt = new ThirdThread(); //使用Lambda表达式创建Callable<Integer>对象 //使用FutureTask来包装Callable对象 FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>)() ->{ int i = 0; for(; i < 100; i++){ System.out.println(Thread.currentThread().getName() + "i值:"+ i); } //call()方法可以有返回值 return i; }); for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+"i值:"+ i); if(i==20){ //实质还是以Callable对象来创建并启动线程的 new Thread(task,"有返回值的线程").start(); } } try { System.out.println("子线程的返回值"+ task.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } }
public class JoinThread extends Thread{ public JoinThread(String name){ super(name); } public void run(){ for (int i = 0; i < 100; i++) { System.out.println(getName() + " " +i); } } public static void main(String[] args) throws InterruptedException{ new JoinThread("新线程").start(); for (int i = 0; i < 100; i++) { if(i == 20){ //当i==20时 jt开始启动,main线程阻塞 JoinThread jt = new JoinThread("被Join的线程"); jt.start(); //main线程调用了jt线程的join()方法,main线程必须等到jt执行结束 //才会向下执行 jt.join(); } System.out.println(Thread.currentThread().getName() + " " +i); } } }
public class DaemonThread extends Thread{ //后台线程的线程执行体与普通线程没有任何区别 public void run(){ for (int i = 0; i < 1000; i++) { System.out.println(getName() + " " +i); } } public static void main(String[] args) throws InterruptedException{ DaemonThread dt = new DaemonThread(); dt.setDaemon(true); dt.start(); for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName()+" "+i); } //----------程序执行到此,前台线程main线程结束------------ //后台线程也随之结束 } }
public class PriorityTest extends Thread{ public PriorityTest(String name){ super(name); } public void run(){ for (int i = 0; i < 50; i++) { System.out.println(getName() + "优先级:" +getPriority()+" i:"+i); } } public static void main(String[] args) throws InterruptedException{ //改变主线程的优先级 Thread.currentThread().setPriority(6); for (int i = 0; i < 30; i++) { if(i == 10){ PriorityTest pt1 = new PriorityTest("低级"); pt1.start(); System.out.println("创建时的优先级:"+pt1.getPriority()+" i:"+i); pt1.setPriority(MIN_PRIORITY); } if(i == 20){ PriorityTest pt2 = new PriorityTest("高级"); pt2.start(); System.out.println("创建时的优先级"+pt2.getPriority()+" i:"+i); pt2.setPriority(MAX_PRIORITY); } } } }
public class DrawThread extends Thread{ //模拟用户账户 private Account account; //当前取钱线程所希望的取的钱数 private double drawAmount; public DrawThread(String name,Account account,double drawAmount){ super(name); this.account = account; this.drawAmount = drawAmount; } //当多个线程修改同一个共享数据时,将涉及数据安全问题 public void run(){ account.draw(drawAmount); } public static void main(String[] args) throws InterruptedException{ Account acct = new Account("123456",1000); new DrawThread("甲",acct,800).start(); new DrawThread("乙",acct,800).start(); } } class Account{ private String accountNo; private double balance; public Account(){} public Account(String accountNo, double balance){ this.accountNo = accountNo; this.balance = balance; } public String getAccountNo() { return accountNo; } public void setAccountNo(String accountNo) { this.accountNo = accountNo; } //因为账户余额不允许随便修改,所以只为balance提供getter方法 public double getBalance() { return balance; } //提供一个线程安全的draw()方法来完成取钱操作 public synchronized void draw(double drawAmount){ if(balance >= drawAmount){ System.out.println(Thread.currentThread().getName()+"取钱成功"+drawAmount); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } balance -= drawAmount; System.out.println("\t余额:"+balance); }else{ System.out.println(Thread.currentThread()+"取钱失败"); } } }
public class test02 { private final ReentrantLock lock = new ReentrantLock(); public void m(){ //加锁 lock.lock(); try{ //需要保证线程安全的代码 //... } //使用finally块来保证释放锁 finally{ lock.unlock(); } } }
public class DeadLock implements Runnable { A a = new A(); B b = new B(); public void init(){ Thread.currentThread().setName("主线程"); a.foo(b); System.out.println("进入主线程"); } public void run(){ Thread.currentThread().setName("副线程"); b.bar(a); System.out.println("进入副线程之后"); } public static void main(String[] args) { DeadLock dl = new DeadLock(); new Thread(dl).start(); dl.init(); } } class A{ public synchronized void foo(B b){ System.out.println("当前线程名:"+Thread.currentThread().getName()+"进入A实例的foo()方法"); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("当前线程名:"+Thread.currentThread().getName()+"企图调用B实例的last()方法"); b.last(); } public synchronized void last(){ System.out.println("进入A类的last()方法内部"); } } class B{ public synchronized void bar(A a){ System.out.println("当前线程名:"+Thread.currentThread().getName()+"进入B实例的bar()方法"); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("当前线程名:"+Thread.currentThread().getName()+"企图调用A实例的last()方法"); a.last(); } public synchronized void last(){ System.out.println("进入了B类的last()方法内部"); } }
public class DeadLockDemo { public static void main(String[] args) { new Thread( new DeadLock(false)).start(); new Thread(new DeadLock(true)).start(); } } class DeadLock implements Runnable{ private static final Object objA = new Object(); private static final Object objB = new Object(); private boolean flag; public DeadLock(boolean flag){ this.flag = flag; } @Override public void run() { while(true){ if(flag){ synchronized(objA){ System.out.println("if objA"); synchronized(objB){ System.out.println("if objB"); } } }else{ synchronized(objB){ System.out.println("else objB"); synchronized(objA){ System.out.println("else objA"); } } } } } }
public class DrawTest { public static void main(String[] args) { //创建一个账户 Account acct = new Account("123",0); new DrawThread("取钱者",acct,800).start(); new DepositThread("存钱者1", acct, 800).start(); new DepositThread("存钱者2", acct, 800).start(); new DepositThread("存钱者3", acct, 800).start(); } } class Account{ private String accountNo; private double balance; //标识账户中是否已经有存款的旗标 private boolean flag = false; public Account(){} public Account(String accountNo, double balance){ this.accountNo = accountNo; this.balance = balance; } public String getAccountNo() { return accountNo; } public void setAccountNo(String accountNo) { this.accountNo = accountNo; } //因为账户余额不允许随便修改,所以只为balance提供getter方法 public double getBalance() { return balance; } //提供一个线程安全的draw()方法来完成取钱操作 public synchronized void draw(double drawAmount){ try { if(!flag){ wait(); }else{ //执行取钱操作 System.out.println(Thread.currentThread().getName()+"取钱"+drawAmount); balance -= drawAmount; System.out.println("账户余额为:"+balance); flag = false; //唤醒其他线程 notifyAll(); } } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void deposit(double depositAmount){ try { //flag为true 表示账户已有人存钱进去,存钱方法阻塞 //当while判断后,wait()方法释放锁,唤醒其他线程去存钱,当存取次数相同时,此程序不会阻塞 // while(flag){ // wait(); // } if(flag){ wait(); }else{ //执行存款操作 System.out.println(Thread.currentThread().getName()+"存款:"+ depositAmount); balance += depositAmount; System.out.println("账户余额:"+balance); flag = true; notifyAll(); } } catch (InterruptedException e) { e.printStackTrace(); } } } class DrawThread extends Thread{ //模拟用户取钱 private Account account; //当前取钱线程所希望取的钱数 private double drawAmount; public DrawThread(String name,Account account,double drawAmount){ super(name); this.account = account; this.drawAmount = drawAmount; } public void run(){ for (int i = 0; i < 300; i++) { System.out.println("取钱次数"+i); account.draw(drawAmount); } } } class DepositThread extends Thread{ //模拟用户账户 private Account account; //当前存钱线程所希望存的钱数 private double depositAmount; public DepositThread(String name , Account account , double depositAmount){ super(name); this.account = account; this.depositAmount = depositAmount; } public void run(){ for (int i = 0; i < 100; i++) { account.deposit(depositAmount); } } }
class Account{ //显示定义Lock对象 private final Lock lock = new ReentrantLock(); //获得指定Lock对象对应的Condition private final Condition cond = lock.newCondition(); private String accountNo; private double balance; //标识账户中是否已经有存款的旗标 private boolean flag = false; public Account(){} public Account(String accountNo, double balance){ this.accountNo = accountNo; this.balance = balance; } public String getAccountNo() { return accountNo; } public void setAccountNo(String accountNo) { this.accountNo = accountNo; } //因为账户余额不允许随便修改,所以只为balance提供getter方法 public double getBalance() { return balance; } //提供一个线程安全的draw()方法来完成取钱操作 public void draw(double drawAmount){ lock.lock(); try { if(!flag){ cond.await(); }else{ //执行取钱操作 System.out.println(Thread.currentThread().getName()+"取钱"+drawAmount); balance -= drawAmount; System.out.println("账户余额为:"+balance); flag = false; //唤醒其他线程 cond.signalAll(); } } catch (InterruptedException e) { e.printStackTrace(); } finally{ lock.unlock(); } } public void deposit(double depositAmount){ lock.lock(); try { //flag为true 表示账户已有人存钱进去,存钱方法阻塞 //当while判断后,wait()方法释放锁,唤醒其他线程去存钱,当存取次数相同时,此程序不会阻塞 // while(flag){ // wait(); // } if(flag){ cond.await(); }else{ //执行存款操作 System.out.println(Thread.currentThread().getName()+"存款:"+ depositAmount); balance += depositAmount; System.out.println("账户余额:"+balance); flag = true; cond.signalAll(); } } catch (InterruptedException e) { e.printStackTrace(); } finally{ lock.unlock(); } } } class DrawThread extends Thread{ //模拟用户取钱 private Account account; //当前取钱线程所希望取的钱数 private double drawAmount; public DrawThread(String name,Account account,double drawAmount){ super(name); this.account = account; this.drawAmount = drawAmount; } public void run(){ for (int i = 0; i < 300; i++) { System.out.println("取钱次数"+i); account.draw(drawAmount); } } }
public class BlockingQueueTest { public static void main(String[] args) { //创建一个容量为1的BlockingQueue BlockingQueue<String> bq = new ArrayBlockingQueue<>(1); //产生3个生产者线程 new Producer(bq).start(); new Producer(bq).start(); new Producer(bq).start(); //启动一个消费者线程 new Consumer(bq).start(); } } class Producer extends Thread{ private BlockingQueue<String> bq; public Producer(BlockingQueue<String> bq){ this.bq = bq; } public void run(){ String[] strArr = new String[]{"Java","Struts","Spring"}; for (int i = 0; i < 999999999; i++) { System.out.println(getName() + "生产者准备生产集合元素"); //尝试放入元素,如果队列已满,则线程被阻塞 try { Thread.sleep(200); bq.put(strArr[i % 3]); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getName()+"生产完成"+bq); } } } class Consumer extends Thread{ private BlockingQueue<String> bq; public Consumer(BlockingQueue<String> bq){ this.bq = bq; } public void run(){ while(true){ System.out.println(getName() + "消费者准备消费集合元素!"); try { Thread.sleep(200); bq.take(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getName()+"消费完成"+bq); } } }
public class ThreadGroupTest { public static void main(String[] args) { //获取主线程所在的线程组,这是所有线程默认的线程组 ThreadGroup mainGroup = Thread.currentThread().getThreadGroup(); System.out.println("主线程祖的名字:"+mainGroup.getName()); System.out.println("主线程是否是后台线程组"+mainGroup.isDaemon()); new MyThread("主线程组的线程").start(); ThreadGroup tg = new ThreadGroup("新线程组"); tg.setDaemon(true); System.out.println("tg线程组是否是后台线程组"+tg.isDaemon()); MyThread tt = new MyThread(tg,"tg线程甲"); tt.start(); new MyThread(tg,"tg组的线程乙").start(); } } class MyThread extends Thread{ //提供指定线程名的构造器 public MyThread(String name){ super(name); } //提供指定线程名、线程组的构造器 public MyThread(ThreadGroup group , String name){ super(group,name); } public void run(){ for (int i = 0; i < 20; i++) { System.out.println(getName() + "线程的i变量"+i); } } }
public class ExHandler { public static void main(String[] args) { //设置主线程的异常处理器 Thread.currentThread().setUncaughtExceptionHandler(new MyExHandler()); int a = 5/0; System.out.println("线程正常结束"); } } class MyExHandler implements Thread.UncaughtExceptionHandler{ @Override public void uncaughtException(Thread t, Throwable e) { System.out.println(t+"线程出现了异常:"+e); } }
public class ThreadPoolTest { public static void main(String[] args) throws Exception{ //创建一个具有固定线程数6的线程池 ExecutorService pool = Executors.newFixedThreadPool(6); //使用lambda表达式创建Runnable对象 Runnable target = () -> { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+"i值:"+i); } }; //向线程池中提交两个线程 pool.submit(target); pool.submit(target); //关闭线程池 pool.shutdown(); } }
public class ForkJoinPoolTest { public static void main(String[] args) throws Exception { ForkJoinPool pool = new ForkJoinPool(); //提交可分解的PrintTask任务 pool.submit(new PrintTask(0,300)); pool.awaitTermination(2, TimeUnit.SECONDS); //关闭线程池 pool.shutdown(); } } class PrintTask extends RecursiveAction{ private static final long serialVersionUID = 1L; //每个“小任务”最多打印50个数 private static final int THRESHOLD = 50; private int start; private int end; //打印从start到end的任务 public PrintTask(int start,int end){ this.start = start; this.end = end; } @Override protected void compute() { //当end与start之间的差小于THRESHOLD时,开始打印 if(end - start < THRESHOLD){ for (int i = start ; i < end; i++) { System.out.println(Thread.currentThread().getName()+"i的值:"+i); } }else{ //当end与start之间的差大于Threshold,即要打印的数超过50个时 //将大任务分解成两个”小任务“ int middle = (start + end)/2; PrintTask left = new PrintTask(start, middle); PrintTask right = new PrintTask(middle, end); //并行执行两个”小任务“ left.fork(); right.fork(); } } }
public class Sum { public static void main(String[] args) throws Exception{ int[] arr = new int[100]; Random rand = new Random(); int total = 0; //初始化100个数字元素 for (int i = 0,len = arr.length; i < len; i++) { int tmp = rand.nextInt(20); //对数组的元素赋值,并将数组元素的值添加到sum总和中 total += (arr[i] = tmp); System.out.println(arr[i]); } System.out.println(total); //创建一个通用池 ForkJoinPool pool = ForkJoinPool.commonPool(); //提交可分解的CaltTask任务 Future<Integer> future = pool.submit(new CalTask(arr,0,arr.length)); System.out.println(future.get()); //关闭线程池 pool.shutdown(); } } class CalTask extends RecursiveTask<Integer>{ //每个"小任务"最多只累加20个数 private static final int THRESHOLD = 20; private int arr[]; private int start; private int end; //累加从start到end的数组元素 public CalTask(int[] arr , int start , int end){ this.arr = arr; this.start = start; this.end = end; } @Override protected Integer compute() { int sum = 0; //当end 与 start 之间的差小于THRESHOLD时,开始进行累加 if(end - start < THRESHOLD){ for(int i = start; i < end ;i++){ sum += arr[i]; } return sum; }else{ //当end与start之间的差大于THRESHOLD,即要累加的数超过20个小时 //将大任务分解成两个"小任务" int middle = (start + end) /2; CalTask left = new CalTask(arr,start,middle); CalTask right = new CalTask(arr,middle,end); //并行执行两个"小任务" left.fork(); right.fork(); //把两个"小任务"累加的结果合并起来 return left.join() + right.join(); } } }
public class ThreadLocalTest { public static void main(String[] args) { //启动两个线程,两个线程共享一个TAccount TAccount at = new TAccount("初始名"); /** * 虽然两个线程共享一个账户,即只有一个账户名 * 但由于账户名是ThreadLocal类型的,所以每个线程都完全拥有 * 各自的账户名副本。因此在i==6之后,将看到两个线程访问同一个 * 账户时出现不同的账户名 */ new MyTest(at,"线程甲").start(); new MyTest(at,"线程乙").start(); } } class TAccount{ //定义一个ThreadLocal类型的变量,该变量将是一个线程局部变量 //每个线程都会保留该变量的一个副本 private ThreadLocal<String> name = new ThreadLocal<String>(); //定义一个初始化name成员变量的构造器 public TAccount(String str){ this.name.set(str); System.out.println("-----" + this.name.get()); } public String getName() { return name.get(); } public void setName(String str) { this.name.set(str);; } } class MyTest extends Thread{ //定义一个Account类型的成员变量 private TAccount account; public MyTest(TAccount account , String name){ super(name); this.account = account; } public void run(){ //循环10次 for (int i = 0; i < 10; i++) { //当i==6时输出将账户名替换成当前线程名 if(i==6){ account.setName(getName()); } //输出同一个账户的账户名和循环变量 System.out.println(account.getName()+" 账户的i值 "+i); } } }
public class Test00 { public static void main(String[] args) { // TODO Auto-generated method stub //第一种: new Thread("我是线程1"){ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+" "+i); } } }.start(); //第二种: new Thread(new Runnable(){ //匿名内部类的实质是创建该类或接口的子类对象 @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+" "+i); } } },"我是线程2").start(); } }
/** * 需求:在指定时间删除指定目录 * @author * */ public class TimerDemo { public static void main(String[] args) throws ParseException { Timer t = new Timer(); String s = "2017-8-15 9:42:00"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date d = sdf.parse(s); t.schedule(new DeleteFolder(),d); } } class DeleteFolder extends TimerTask{ @Override public void run() { File srcFolder = new File("demo"); deleteFolder(srcFolder); } //递归删除目录 public void deleteFolder(File srcFolder){ File[] fileArr = srcFolder.listFiles(); if(fileArr != null){ for(File file:fileArr){ if(file.isDirectory()){ deleteFolder(file); }else{ System.out.println(file.getName()+":"+file.delete()); } } System.out.println(srcFolder.getName()+":"+srcFolder.delete()); } } }