1.多线程实现方式
1.继承Thread类,但是对于单继承的Java,限制很大
2.实现Runnable接口
public class DemoThread {
public static void main(String[] args) {
Play play = new Play();
Thread thread = new Thread(play);
thread.start();
}
}
class Play implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0; i<10;i++){
System.out.println("线程:"+i);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println();
}
}
3.使用Timer和TimerTask组合
最后一种实现多线程的方式,就是使用java.util包中的Timer和TimerTask类实现多线程,使用这种方式也可以比较方便的实现线程。在这种实现方式中,Timer类实现的是类似闹钟的功能,也就是定时或者每隔一定时间触发一次线程。其实,Timer类本身实现的就是一个线程,
只是这个线程是用来实现调用其它线程的。而TimerTask类是一个抽象类,该类实现了Runnable接口,所以按照前面的介绍,该类具备多线程的能力。
在这种实现方式中,通过继承TimerTask使该类获得多线程的能力,将需要多线程执行的代码书写在run方法内部,然后通过Timer类启动线程的执行。
在实际使用时,一个Timer可以启动任意多个TimerTask实现的线程,但是多个线程之间会存在阻塞。所以如果多个线程之间如果需要完全独立运行的话,
最好还是一个Timer启动一个TimerTask实现。
public class DemoTimerMark {
public static void main(String[] args) {
Timer timer1 = new Timer();
Timer timer2 = new Timer();
MyTimerTask task1 = new MyTimerTask(1);
timer1.schedule(task1, 1000);
MyTimerTask task2 = new MyTimerTask(2);
timer2.schedule(task2, 1000);
}
}
class MyTimerTask extends TimerTask{
private int count;
public MyTimerTask(int i){
this.count = i;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0; i<4;i++){
System.out.println("线程"+this.count+":"+i);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("========================================END=====================================");
}
}
//
2,线程状态
1.新生状态 new
2.被阻塞状态 blocked
3.可运行状态 runnable
4.等待 waiting
5.计时等待 time waiting
6.被终止 terminated
2.被阻塞状态 blocked
3.可运行状态 runnable
4.等待 waiting
5.计时等待 time waiting
6.被终止 terminated
3.线程细节
1.线程优先级setPriority方法可以为线程设置优先级 ,优先级默认继承父线程的优先级 ,线程优先级高度依赖于操作系统。Java线程优先级会被映射到寄主主体平台的优先级上面
2.守护线程 setDaemon(true)
为其他线程提供服务的线程。如计时器线程。当只有一个守护线程时,虚拟机会退出(守护线程永远不要去访问固件资源,因为他会随时中断)
4.锁 方法一:Lock/Condition 方法二:synchronized
1.条件对象一个锁可以有多个条件,每个条件上可以有多个线程等待,通过调用await()方法,可以让线程在该条件下等待。当调用signalAll()方法,又可以唤醒该条件下的等待的线程。
有关Condition接口的API可以具体参考JavaAPI文档。
2.synchronized 用此关键词声明的方法必须要获得程序的内部锁
3.同步阻塞 使用一个对象的锁来实现额外的原子操作称为 客户端锁定
5,银行取款问题
// 银行取款问题
// 不加锁
public class BankProblem {
public static void main(String[] args) {
Bank bank = new Bank();
for(int i=0;i<1000;i++){
Transable transable = new Transable(bank,i);
Thread thread =new Thread(transable);
thread.start();
}
}
}
class Bank{
private int[] count = new int[10];
public Bank(){
for(int i=0;i<10;i++){
this.count[i] = 1000;
}
}
public void trans(String name,int from,int to,int n) throws InterruptedException{
if(count[from]>n){
count[from]-=n;
System.out.print("");
count[to]+=n;
System.out.println(name+" : 用户"+from+"向用户"+to+"转入:"+n+" 目前总资金为:"+this.toString());
}
}
@Override
public String toString() {
// TODO Auto-generated method stub
int out = 0;
for(int i:count)
out+=i;
return out+"";
}
public int[] getCount() {
return count;
}
public void setCount(int[] count) {
this.count = count;
}
}
class Transable implements Runnable{
private Bank bank;
private int i;
public Transable(Bank bank,int i){
this.bank = bank;
this.i = i;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
bank.trans("线程"+i, RandomUtils.nextInt(10), RandomUtils.nextInt(10), RandomUtils.nextInt(1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
上述代码中会发生线程安全问题,对此有下面几个解决方案
//=============================================================。
解决方法一
public synchronized void trans(String name,int from,int to,int n) throws InterruptedException{
if(count[from]>n){
count[from]-=n;
System.out.print("");
count[to]+=n;
System.out.println(name+" : 用户"+from+"向用户"+to+"转入:"+n+" 目前总资金为:"+this.toString());
}
}
// 方法二
public void trans(String name,int from,int to,int n) throws InterruptedException{
lock.lock();
try{
while(count[from]>n){
count[from]-=n;
System.out.print("");
count[to]+=n;
System.out.println(name+" : 用户"+from+"向用户"+to+"转入:"+n+" 目前总资金为:"+this.toString());
}
}finally{
lock.unlock();
}
}
// 用条件对象改进 解决方法三
// 测试时,为试着将n改为 2*n 由于条件对象,照样可以运行,但是几秒之后发生死锁问题
public void trans(String name,int from,int to,int n) throws InterruptedException{
lock.lock();
try{
while(count[from]<n)
condition.await();
count[from]-=n;
System.out.print("");
count[to]+=n;
System.out.println(name+" : 用户"+from+"向用户"+to+"转入:"+n+" 目前总资金为:"+this.toString());
condition.signalAll();
}finally{
lock.unlock();
}
}
// 用synchronized 方法代替显式的锁,很方便,代码如下,与上面的代码功能一样 解决方法四
public synchronized void trans(String name,int from,int to,int n) throws InterruptedException{
while(count[from]<n)
wait();
count[from]-=n;
System.out.print("");
count[to]+=n;
System.out.println(name+" : 用户"+from+"向用户"+to+"转入:"+n+"目前总资金为:"+this.toString());
notifyAll();
}
// 前面3,4方法都有死锁。有一个解决方法是,给wait()一个时间限制,超时后,自动退出
public void trans(String name,int from,int to,int n) throws InterruptedException{
lock.lock();
try{
while(count[from]<n)
if(!condition.await(100, TimeUnit.MILLISECONDS)){
System.out.println("遇到死锁,此交易退出!!");
return;
}
count[from]-=n;
count[to]+=n;
System.out.println(name+" : 用户"+from+"向用户"+to+"转入:"+n+" 目前总资金为:"+this.toString());
condition.signalAll();
}finally{
lock.unlock();
}
}
6.阻塞队列
将线程安全等问题交给阻塞队列 public class BlockingQueueTest {
public static String src = "/usr/spring-framework-2.5.5_src";
public static void main(String[] args) {
BlockingQueue<File> queue = new ArrayBlockingQueue<File>(19999);
new Thread(new Find(queue, src)).start();
for(int i = 0;i<10;i++)
new Thread(new search(queue, "volatile")).start();
}
}
class Find implements Runnable{
private BlockingQueue<File> queue;
private String firstFileName;
public Find(BlockingQueue<File> queue, String firstFileName) {
super();
this.queue = queue;
this.firstFileName = firstFileName;
}
@Override
public void run() {
File file = new File(firstFileName);
try {
findFile(file);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void findFile(File file) throws InterruptedException{
if(file.isDirectory()){
File[] f = file.listFiles();
for(File tmp:f){
findFile(tmp);
}
}else{
if(!queue.offer(file, 1000, TimeUnit.MILLISECONDS))
System.out.println("添加失败");
}
}
}
class search implements Runnable{
private BlockingQueue<File> queue;
private String keyWords;
public search(BlockingQueue<File> queue, String keyWords) {
super();
this.queue = queue;
this.keyWords = keyWords;
}
@Override
public void run() {
// TODO Auto-generated method stub
boolean b = true;
try {
while(b){
File f = queue.poll(1000, TimeUnit.MILLISECONDS);
if(f==null){
b = false;
}else{
Scanner in = new Scanner(f);
int len = 0;
String tmp = "";
while(in.hasNext()){
len++;
tmp = in.nextLine();
if(tmp.contains(keyWords)){
System.out.println("文件名为:"+f.getName()+" 第"+len+"行 : ");
System.out.println(" "+tmp);
}
}
}
queue.peek();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
}
}
}
7.Future 封装一个有返回值的一部运行任务,相当于有返回值的Runnable
//Callable 相当于一个带有参数的Runable
public class FutureTest {
public static String src = "/usr/spring-framework-2.5.5_src/src";
public static String key = "class";
public static void main(String[] args) throws InterruptedException, ExecutionException {
FutureTask<Integer> futureTask = new FutureTask<Integer>(new Find(new File(src), key));
new Thread(futureTask).start();
System.out.println("个数为:"+futureTask.get());
}
}
class Find implements Callable<Integer>{
private File firstFile;
private String key;
private int count;
public Find(File file,String key) {
super();
this.firstFile = file;
this.key = key;
}
private Integer findFile(File file) throws InterruptedException, ExecutionException{
List<Future<Integer>> list = new ArrayList<Future<Integer>>();
if(file.isDirectory()){
File[] f = file.listFiles();
for(File tmp:f){
if(tmp.isDirectory()){
FutureTask<Integer> futureTask = new FutureTask<Integer>(new Find(tmp, key));
list.add(futureTask);
new Thread(futureTask).start();
}else{
if(search(tmp))
count++;
}
}
}else{
if(search(file))
count++;
}
for(Future<Integer> future:list){
count+=future.get();
}
return count;
}
public boolean search(File f) {
try {
if(f==null){
return false;
}else{
Scanner in = new Scanner(f);
String tmp = "";
while(in.hasNext()){
tmp = in.nextLine();
if(tmp.contains(key)){
return true;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
}
return false;
}
@Override
public Integer call() throws Exception {
try {
return findFile(firstFile);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
8,连接池
//简单使用连接池只需要将上面的代码修改下 public class ThreadPoolTest {
public static String src = "/usr/spring-framework-2.5.5_src/src";
public static String key = "class";
public static void main(String[] args) throws InterruptedException, ExecutionException {
// FutureTask<Integer> futureTask = new FutureTask<Integer>(new FindByPool(new File(src), key));
// new Thread(futureTask).start();
// System.out.println("个数为:"+futureTask.get());
ExecutorService service = Executors.newCachedThreadPool();
Future<Integer> future = service.submit(new FindByPool(new File(src), key,service));
System.out.println(future.get());
}
}
class FindByPool implements Callable<Integer>{
private File firstFile;
private String key;
private ExecutorService service;
private int count;
public FindByPool(File file, String key2, ExecutorService service) {
// TODO Auto-generated constructor stub
this.firstFile = file;
this.key = key2;
this.service = service;
}
private Integer findFile(File file) throws InterruptedException, ExecutionException{
List<Future<Integer>> list = new ArrayList<Future<Integer>>();
if(file.isDirectory()){
File[] f = file.listFiles();
for(File tmp:f){
if(tmp.isDirectory()){
FindByPool pool = new FindByPool(tmp,key,service);
list.add(service.submit(pool));
}else{
if(search(tmp))
count++;
}
}
}else{
if(search(file))
count++;
}
for(Future<Integer> future:list){
count+=future.get();
}
return count;
}
public boolean search(File f) {
try {
if(f==null){
return false;
}else{
Scanner in = new Scanner(f);
String tmp = "";
while(in.hasNext()){
tmp = in.nextLine();
if(tmp.contains(key)){
return true;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
}
return false;
}
@Override
public Integer call() throws Exception {
try {
if(firstFile!=null)
return findFile(firstFile);
else return 0;
} catch (InterruptedException e) {
e.printStackTrace();
}
return 0;
}
}
上面就是简单使用Java多线程的部分,还有关于线程安全与高并发部分的内容没有写出来.尽快补上