1、13章笔记及代码 1什么是线程? 可以看成是程序的一次执行过程,牵扯很少的系统资源。线程的开发:线程两种实现方式?1.继承thread类 public class MyFirstThread extends Thread Override public void run() / TODO Auto-generated method stub for(int i=0;i1000;i+) System.out.println(这是我的第1个线程!); 应该如何启动该线程,让他开始工作。Main() Thread t=new MyFirstThread(); t.start();多个线程之间的执行时
2、相互独立的。启动一个线程用thread对象的start方法。启动不是马上就执行run方法,要等到cpu分配过来才能执行。如果直接调用thread的run方法,不会启动一个线程,这时候就会把run方法当成一个普通的方法来执行,这个时候多个线程之间就是按照顺序执行。举例:一个打印一串字母,一个打印一串数字,看看两个线程打印情况,让两个线程同时启动。package com.wdp;public class Test public static void main(String args) /打印字母的线程 Thread t=new PrintLetterThread(); Thread t1=new
3、 PrintNumberThread(); /开启两个线程 t.start(); t1.start(); /* * print letter * author chidianwei * */class PrintLetterThread extends Thread Override public void run() / TODO Auto-generated method stub for(int i=0;i1000;i+) System.out.println(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa); System.out.prin
4、tln(); /*print number*/class PrintNumberThread extends Thread Override public void run() / TODO Auto-generated method stub for(int i=0;i1000;i+) System.out.println(0000000000000000000000000000000000000000000000); System.out.println(); 2.实现runnable接口/*print number*/class PrintNumberThread implements
5、Runnable Override public void run() / TODO Auto-generated method stub for(int i=0;i1000;i+) System.out.println(0000000000000000000000000000000000000000000000); System.out.println(); 启动一个线程: Runnable t1=new PrintNumberThread(); /开启两个线程 Thread number=new Thread(t1); number.start();线程的状态,状态之间如何切换?初始状态-
6、start-可运行状态(就绪状态)-分配cpu-运行状态(如果时间片到期可能回到可运行状态)-run-结束状态 线程阻塞两种方式:1.如果正在运行的线程调用sleep方法,会进入一个阻塞状态等到sleep时间已到,重新进入可运行状态2.第二种方法用thread的join阻塞注意:用sleep控制程序阻塞是不准确的,使用join方法可以使程序的控制变得准确。思考题?有几个线程?打印结果是什么?可否在main方法里面直接调用run方法,这和用start方法有何区别?public class Test public static void main(String args) / TODO Auto-
7、generated method stub TestThread tt = new TestThread(); tt.run(); System.out.println(Thread.currentThread().getName(); System.out.println(Printed by main thread); class TestThread extends Thread static int i = 0; final static int MAX_I = 10; Override public void run() / TODO Auto-generated method st
8、ub System.out.println(Thread.currentThread().getName(); while (i MAX_I) System.out.println(i+); 线程阻塞(join方式)在一个线程里面持有另一个线程对象,调用对方的join方法,就会让当前线程处于等待,一直等到对方线程运行结束,才开始当前线程的运行。线程状态 初始化-可运行-运行-结束处在运行状态的线程可以进入阻塞,当阻塞解除的时候进入可运行状态,阻塞有两种方式:不精确的方式是sleep,还有一种调用另一个线程对象的join方法,当另一个线程执行完,再解除当前线程的阻塞。线程的同步线程的同步:什么叫
9、多线程?同时对一个资源操作会有什么问题?多个线程操作同一个临界资源可能会出现访问冲突或者临界值不符合预期要求的情况,这个时候我们可以使用synchronized块对其进行包围。注意里面的参数是一个对象。有两种方式:1.synchronized(lock)public void deposit(double count) throws InterruptedException System.out.println(存入的金额:+count); synchronized (lock) double now = balance + count; Thread.sleep(100);/存钱操作用时0.
10、1秒钟 balance = now; System.out.println(存入后金额:+balance); public void withdraw(double count) throws InterruptedException System.out.println(取出金额:+count); synchronized (lock) double now = balance - count; Thread.sleep(200);/取钱操作用时0.2秒钟 balance = now; System.out.println(取出后金额:+balance); 2.在方法前面直接加上synchr
11、onized public synchronized void deposit(double count) throws InterruptedException System.out.println(存入的金额:+count); double now = balance + count; Thread.sleep(100);/存钱操作用时0.1秒钟 balance = now; System.out.println(存入后金额:+balance); public synchronized void withdraw(double count) throws InterruptedExcept
12、ion System.out.println(取出金额:+count); double now = balance - count; Thread.sleep(200);/取钱操作用时0.2秒钟 balance = now; System.out.println(取出后金额:+balance); 注意,如果多个线程出现需要使用多个锁的情况,需要在任何方法中保持锁的顺序一致。才不至于出现死锁。public void deposit(double count) throws InterruptedException System.out.println(存入的金额:+count); synchro
13、nized (lock1) double now = balance + count; Thread.sleep(100);/存钱操作用时0.1秒钟 synchronized(lock2) balance = now; System.out.println(存入后金额:+balance); public void withdraw(double count) throws InterruptedException System.out.println(取出金额:+count); synchronized (lock1) double now = balance - count; Thread.
14、sleep(200);/取钱操作用时0.2秒钟 synchronized(lock2) balance = now; System.out.println(取出后金额:+balance); Object的wait,notify和notifyAll# 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj). 代码段内。# 调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj). 代码段内唤醒A。# 当obj.wait()方法返回后,线程A需要再次获得obj锁,才
15、能继续执行。#如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。java新特性之concurrentThread处理多线程问题 摒弃synchronized java.util.concurrent.locks.LOCK lock() unlock() tryLock() 摒弃wait() notify() notifyAll() java.util.concurrent.locks. Condition awaite() signal() signalAll()线程之间进行合作 用到锁的wait和noti
16、fyAllpackage com.wdp;public class Card private Object lock=new Object(); private double balance;public double getBalance() return balance;public void setBalance(double balance) this.balance = balance;/* * withdraw */public void withdraw(double money) while(true) synchronized(this) System.out.println
17、(当前用户取款金额是:+money); double now=balance-money; try Thread.sleep(100); catch (InterruptedException e) / TODO Auto-generated catch block e.printStackTrace(); while(this.balance-money2000) try this.wait(); catch (InterruptedException e) / TODO Auto-generated catch block e.printStackTrace(); this.setBala
18、nce(this.balance+money); System.out.println(存款后的余额是:+this.balance); this.notifyAll(); /synchr /while /* * 存款线程 */ class DepositThread extends Thread private Card card; public DepositThread(Card card) this.card=card; Override public void run() / TODO Auto-generated method stub card.deposit(100); /* 取
19、款线程 */ class WithdrawThread extends Thread private Card card; public WithdrawThread(Card card) this.card=card; Override public void run() / TODO Auto-generated method stub card.withdraw(50); 实例代码:考虑一道淘宝的笔试题: 一个长度的30000的int数组,其中放随机数,利用多核的优势,求数组中元素的和。 TestArray.javapackage com.exer;import java.util.Ra
20、ndom;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;public class TestBigArray /* * 一个长度的30000的int数组,其中放随机数,利用多核的优势,求数组中元素的和。 */ public static void main(String args) throws Interrupted
21、Exception, ExecutionException / TODO Auto-generated method stub long total=0;/存储综合/ 1.创建数组,赋值随机数 int big=new int30000000; Random r=new Random(); for(int i=0;i30000000;i+) bigi=r.nextInt(100); / 2.计算大数组元素的和 ExecutorService pool=Executors.newCachedThreadPool(); for(int i=0;i6;i+) int start=i*5000000;
22、int end=(i+1)*5000000; SumThread task=new SumThread(big,start,end); Future f=pool.submit(task); long part=f.get(); total+=part; System.out.println(total:+total); SumThread.javapackage com.exer;import java.util.concurrent.Callable;public class SumThread implements Callable private int big; private int start; private int end; public SumThread(int big, int start, int end) this.big = big; this.start = start; this.end = end; Override public Long call() throws Exception / TODO Auto-generated method stub long sum=0; for(int i=start;iend;i+) sum+=bigi; return sum;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1