-------
android培训、
java培训、期待与您交流! ----------
总结:多线程并不能让程序运行的更快,但是多线程能让程序同时处理的事情变得更多,通过一些设计,可以让程序更快的完成任务.例如搜索用户磁盘中存在的文件.
1,对于多线程来说,首先要考虑的就是线程安全问题.
先来看一个卖票系统的例子,车站要卖100张票,有2个卖票窗口,
要解决线程安全问题就需要做到同步互斥.
把2个线程要访问的共享数据存放在一个类中,
注意:synchronized(x),锁的钥匙一定要用同一个,不然就是不同的锁,无法实现互斥的效果,
同一段代码中最好别出现2个锁,不然会造成死锁.
package cn.hmm.thread2;
//卖票系统,每个线程卖一张
public class ThreadSaletitck{
public static void main(String[] args){
res1 r = res1.get();
Thread d1 = new Thread(new sale1(r));
Thread d2 = new Thread(new sale2(r));
d1.start();
d2.start();
}
}
//设计一个单例,用饿汉式
class res1{
public int num = 100;
public boolean flag = true;
private res1(){
}
static res1 Obj = null;
public static res1 get(){
if(Obj==null){
Obj = new res1();
}
return Obj;
}
}
//售票站1
class sale1 implements Runnable
{
private res1 r;
sale1(res1 r){
this.r = r;
}
public void run(){
while(true){
synchronized(r){
if(r.flag){
System.out.println("sale1 "+ r.num--);
r.flag = false;
if(r.num<=1)
return;
}
}
}
}
}
//售票站2
class sale2 implements Runnable{
private res1 r;
sale2(res1 r){
this.r = r;
}
public void run(){
while(true){
synchronized(r){
if(!r.flag){
System.out.println("sale2 "+ r.num--);
r.flag = true;
if(r.num<=1)
return;
}
}
}
}
}
2,再来看一个例子:主线程先循环100次,然后再子线程循环10次,再主线程循环100次,子线程循环10次.....一直这样循环50次.
要解决这个问题也要用到同步互斥,可以把主线程循环100次和子线程循环10次写到2个方法上门,然后再封装到一个类中.
再创建出一个对象,调用这个对象上的2个方法.在这个类中用一个共享的布尔型变量作为标记,实现等待唤醒操作,代码如下:
package cn.hmm.thread;
public class TraditionalThreadCommunication {
/**
* 主线程先循环50次,然后再子线程循环10次,再主线程循环50次,子线程循环10次.....
* 一直这样循环50次
*
*/
public static void main(String[] args) throws InterruptedException {
// TODO 自动生成的方法存根]
final Business business = new Business();
new Thread(new Runnable(){
public void run(){
for(int i=1;i<=50;i++){
try {
business.sun(i);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}).start();
for(int i=1;i<=50;i++){
business.main(i);
}
}
}
class Business{
boolean bShouldSub = true;
public synchronized void sun(int i) throws InterruptedException{
while(bShouldSub){
this.wait();
}
for(int j=1;j<=10;j++){
System.out.println("sub thread:"+i+" loops:"+j);
}
bShouldSub = true;
this.notify();
}
public synchronized void main(int i) throws InterruptedException{
while(!bShouldSub){
this.wait();
}
for(int j=1;j<=100;j++){
System.out.println("main thread:"+i+" loops:"+j);
}
bShouldSub = false;
this.notify();
}
}
3,创建线程的传统方法:
package cn.hmm.thread;
public class TraditionalThread {
/**
* @param args
*/
public static void main(String[] args) {
createThread1();
createThread2();
createThread3();
}
//子类的run()方法覆盖了父类的run()方法
private static void createThread3() {
new Thread(new Runnable(){
public void run(){
for(int i=0;i<99;i++){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println("Runnable:"+Thread.currentThread().getName());
}
}
}){
public void run(){
for(int i=0;i<99;i++){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println("Thread:"+Thread.currentThread().getName());
}
}
}.start();
}
//方法二:常用的方法
private static void createThread2() {
Thread thread2 = new Thread(new Runnable(){
public void run(){
for(int i=0;i<99;i++){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
});
thread2.start();
}
//方法一:不常用
private static void createThread1() {
Thread thread = new Thread(){
public void run(){
for(int i=0;i<99;i++){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
//System.out.println(this.getName());
}
}
};
thread.start();
}
}
4,定时器:
package cn.hmm.thread;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
//实现一次2秒一次4秒的交替,无限次的定时效果
class MyTimetTask extends TimerTask{
private static int count = 0;
public void run(){
count = (count+1)%2;
System.out.println("bombing!");
new Timer().schedule(new MyTimetTask(), 2000+2000*count);
}
}
public class TraditionalTimerTest {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//creatTimer1();
creatTimer2();
}
//实现一次2秒一次4秒的交替,无限次的定时效果
private static void creatTimer2() {
new Timer().schedule(new MyTimetTask(), 2*1000);
while(true){
System.out.println(new Date().getSeconds());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
@SuppressWarnings("deprecation")
private static void creatTimer1() {
new Timer().schedule(new TimerTask(){
public void run(){
System.out.println("bombing!");
}
}, 10*1000,3*1000);
while(true){
System.out.println(new Date().getSeconds());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
5,线程内数据共享,各线程数据不受到影响:
package cn.hmm.thread;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class ThreadScopeShareData {
private static int data = 0;
private static Map<Thread, Integer> threadData = new HashMap<Thread,Integer>();
/**
* @param args
*/
public static void main(String[] args) {
// TODO 自动生成的方法存根
for(int i=0;i<2;i++){
new Thread(new Runnable(){
public void run(){
data = new Random().nextInt(1000);
System.out.println(Thread.currentThread().getName()+" data = "+data);
threadData.put(Thread.currentThread(),data);
new A().get();
new B().get();
}
}).start();
}
/*new Thread(new Runnable(){
public void run(){
new A().get();
new B().get();
}
}).start();*/
}
static class A{
public void get(){
int data = threadData.get(Thread.currentThread());
System.out.println("A from "+Thread.currentThread().getName()+" get data:"+data);
}
}
static class B{
public void get(){
int data = threadData.get(Thread.currentThread());
System.out.println("B from "+Thread.currentThread().getName()+" get data:"+data);
}
}
}
package cn.hmm.thread;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class ThreadScopeShareData2 {
private static int data = 0;
private static Map<Thread, Integer> threadData = new HashMap<Thread,Integer>();
/**
* @param args
*/
private static ThreadLocal<Integer> x = new ThreadLocal<Integer>();
public static void main(String[] args) {
// TODO 自动生成的方法存根
for(int i=0;i<2;i++){
new Thread(new Runnable(){
public void run(){
data = new Random().nextInt(1000);
x.set(data);
System.out.println(Thread.currentThread().getName()+" data = "+data);
//threadData.put(Thread.currentThread(),data);
new A().get();
new B().get();
}
}).start();
}
/*new Thread(new Runnable(){
public void run(){
new A().get();
new B().get();
}
}).start();*/
}
static class A{
public void get(){
//int data = threadData.get(Thread.currentThread());
int data = x.get();
System.out.println("A from "+Thread.currentThread().getName()+" get data:"+data);
}
}
static class B{
public void get(){
//int data = threadData.get(Thread.currentThread());
int data = x.get();
System.out.println("B from "+Thread.currentThread().getName()+" get data:"+data);
}
}
}
6, JDK1.5的新特性 线程池:
package cn.hmm.thread2;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO 自动生成的方法存根
//test1();
test2();
}
private static void test2() {
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(3);
threadPool.schedule(new Runnable(){
public void run(){
System.out.println("Bombing");
}
},
10,
TimeUnit.SECONDS);
threadPool.shutdown();
long start =System.currentTimeMillis();
for(int i=0;i<20;i++){
System.out.println(System.currentTimeMillis()-start);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
private static void test1() {
//ExecutorService threadPool = Executors.newFixedThreadPool(3);//固定的线程池
ExecutorService threadPool = Executors.newCachedThreadPool();//缓存的线程池
for(int i=1;i<=10;i++){
final int task =i;
threadPool.execute(new Runnable(){
public void run(){
for(int j=1;j<=10;j++){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" is looping of "+j+" form task_"+task);
}
}
});
}
System.out.println("all of 10 tasks have commotted!");
threadPool.shutdown();
}
}
7,模拟处理16行日志,下面的代码产生了16个日志对象,当前代码需要运行16秒才能打印完这些日志。
修改程序代码,开四个线程让这16个对象在4秒钟打完。
package cn.hmm.thread2;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args){
System.out.println("begin:"+(System.currentTimeMillis()/1000));
/*模拟处理16行日志,下面的代码产生了16个日志对象,当前代码需要运行16秒才能打印完这些日志。
修改程序代码,开四个线程让这16个对象在4秒钟打完。
*/
ExecutorService threadPool = Executors.newFixedThreadPool(4);
for(int i=0;i<16;i++){ //这行代码不能改动
final String log = ""+(i+1);//这行代码不能改动
{
threadPool.execute(new Runnable(){
public void run(){
Test.parseLog(log);
}
});
}
}
}
//parseLog方法内部的代码不能改动
public static void parseLog(String log){
System.out.println(log+":"+(System.currentTimeMillis()/1000));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
总结:多线程并不能让程序运行的更快,但是多线程能让程序同时处理的事情变得更多,通过一些设计,可以让程序更快的完成任务.例如搜索用户磁盘中存在的文件.
------- Windows Phone 7手机开发、.Net培训、期待与您交流! -------
详细请查看:www.itheima.com