您的位置:首页 > 编程语言 > Java开发

Java 多线程

2016-04-19 23:15 621 查看

1.java多线程的两种形式

1.1Thread子类形式

public class MyThread extends Thread{
@Override
public void run() {
for (int i=0;i<500;i++){
System.out.println( getName()+":"+i);
}
}
}

public class ThreadDemo {
public static void main(String[] args) throws InterruptedException {
MyThread myThread1=new MyThread();
MyThread myThread2=new MyThread();
myThread1.start();
myThread2.start();
System.out.println("over...");
}
}


1.2 Runable形式

class MyRunable implements Runnable{
@Override
public void run() {
for (int i=0;i<200;i++){
//注意这里调用线程名称的方式
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}

public class ThreadRunableDemo {
public static void main(String[] args) {
Runnable r1= new MyRunable();
new Thread(r1,"clow").start();
new Thread(r1,"jop").start();

//当然也可以使用内部类
Runnable r2=new MyRunable(){
@Override
public void run() {
for (int i=10;i<120;i++){
//注意这里调用线程名称的方式
System.out.println(Thread.currentThread().getName() + ":" + (char)i);
}
}
};
new Thread(r2,"alex").start();
}

}


1.3 内部类线程

内部类可以类比于C#的委托-拉姆达表达式,同层次的变量在run方法是可以直接使用的,这和拉姆达表达式一样
public class InnerThreadDemo {
public static void main(String[] args) {
//继承Thread类实现多线程
new Thread(){
@Override
public void run() {
for (int i=0;i<1000;i++){
System.out.println(Thread.currentThread().getName()+": "+i);
}
}
}.start();

//使用Runnable实现
new Thread(new Runnable() {
@Override
public void run() {
for (int i=0;i<1000;i++){
System.out.println(Thread.currentThread().getName()+": "+i);
}
}
}).start();
}
}


1.4二者的比较

Runable解决了java单继承类的局限问题,而且它减少了代码的耦合性,所有推荐使用第二种方法!

2.电影票问题

假设一家电影院有3个电影售票窗口,同时出售《复仇者联盟4》的电影票共100张,如何模拟?

2.1Thread子类实现形式

class TicketTread extends Thread {

private static int ticketnum = 100;

@Override
public void run() {
while(ticketnum>0){
System.out.println("windows_"+ getName()+":The current ticket number is "+ticketnum--);
}
}
}

class TicketTreadDemo {
public static void main(String[] args) {
TicketTread t1=new TicketTread();
TicketTread t2=new TicketTread();
TicketTread t3=new TicketTread();
t1.start();
t2.start();
t3.start();
}
}


2.2Runable 实现形式

class Ticket implements Runnable {

private int ticketnum = 100;

@Override
public void run() {
while(ticketnum>0){
System.out.println("windows_"+Thread.currentThread().getName()+":The current ticket number is "+ticketnum--);
}
}
}

class TicketRunableDemo {
public static void main(String[] args) {
Ticket t =new Ticket();
new Thread(t,"1").start();
new Thread(t,"2").start();
new Thread(t,"3").start();
}
}


从上面的2例子可以看出对于相同的代码,使用runable的方法更灵活方便,但是他们都还存在一个问题,比如某一张票会被卖了2次,这就是所谓的临界区问题了。

2.3Runable 最终实现形式

如上的售票必须使用同步才行,java的synchronized方法和C#的lock方法类似。

class Ticket implements Runnable {

private int ticketnum = 100;
private Object obj = new Object();
@Override
public void run() {
synchronized (obj) {
while (ticketnum > 0) {
System.out.println("windows_" + Thread.currentThread().getName() + ":The current ticket number is " + ticketnum--);
}
}
}
}


当然也可以使用同步方法放在run里面,但类是实例类的时候,它锁的对象的this; 当方法是静态的时候,它锁的是类的Xxx.class的字节码对象
public synchronized void sellTicket(){
while (ticketnum > 0) {
System.out.println("windows_" + Thread.currentThread().getName() + ":The current ticket number is " + ticketnum--);
}
}


继jdk5推出了类似PV操作的上锁和解锁操作
class Ticket implements Runnable {
private int ticketnum = 100;
Lock lock=new ReentrantLock(); //实例化一个锁
@Override
public void run() {
try {
lock.lock(); //上锁
while (ticketnum > 0) {
System.out.println("windows_" + Thread.currentThread().getName() + ":The current ticket number is " + ticketnum--);
}
}finally {
lock.unlock(); //解锁
}
}
}


2.线程池

1.Runable类型
lass ThreadPool implements Runnable {
@Override
public void run() {
for (int i=0;i<200;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}

class ThreadPoolDemo{
public static void main(String[] args) {
ExecutorService pool= Executors.newFixedThreadPool(2);//创建包含2个线程的线程池
pool.submit(new ThreadPool());
pool.submit(new ThreadPool());
//此时线程执行完会被回收,使用下面方法结束线程池
pool.shutdown();
}
}


2.Callable类型
其和C#中的BackgroundWork类似,都是执行一段代码并返回结果。而在java中其自动阻塞主线程效果
class MyCallable implements Callable<Integer> {

private int number;

public MyCallable(int number){
this.number=number;
}

@Override
public Integer call() throws Exception {
int sum=0;
for (int i=1;i<=number;i++){
sum+=i;

}
Thread.sleep(7000);
return sum;
}
}

class MyCallableDemo{
public static void main(String[] args) throws Exception {
ExecutorService pool= Executors.newFixedThreadPool(2);
Future<Integer> f1=pool.submit(new MyCallable(100));
Future<Integer> f2=pool.submit(new MyCallable(200));
int i1=f1.get();
int i2=f2.get();
System.out.println("打印输出");
System.out.println(i1);//5050
System.out.println(i2);//20100
}
}


3.定时器

如下代码为当前显示时间
//schedule(TimerTask task, long delay, long period)
//period为时间间隔

class MyTask extends TimerTask{

@Override
public void run() {
System.out.println(new Date().toString());
}
}

class TimerDemo {
public static void main(String[] args) {
Timer t=new Timer();
TimerTask task=new MyTask();
t.schedule(task, 0, 1000); //第一次无延迟,每秒执行一次
//t.cancel(); //干掉时间任务的子线程,才能推出主线程
System.out.println("over..");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: