线程的创建两种实现
一种是继承 Thread 类(该类已实现 Runnable 接口)
一种是直接实现 Runnable 接口
Thread 类的定义如下:
public class Thread extends Object implements Runnable
{
}
可发现 Thread 类实现了 Runnable 接口,所以直接继承 Thread 类即可,
并将 线程的程序代码 写在 run() 方法内,即可重写 Thread 类的 run() 方法
即可创建线程,多线程定义格式如下:
[public] class 类名 extends Thread
{
属性;
方法;
public void run() // 重写 Thread 类的 run() 方法
{
// 线程代码
}
}
Thread 类属于 java.lang 包,系统在运行时会自动导入,所以不需要使用
import 关键字显式导入 Thread 类
//以下用 Thread 类实现
public class Hi extends Thread
{
private String name;
public Hi(){}
public Hi(String name)
{
// Thread 类中的 run() 方法
setName(name);
}
public void run()
{
for (int i=0;i <=10 ;i++ )
{
// 输出当前线程
System.out.println("当前运行的线程:"+getName()+", i="+i);
}
}
public static void main(String[] args)
{
// 创建实例1
Hi t1 = new Hi("线程-1");
// 创建实例2
Hi t2 = new Hi("纯程-2");
// 启动线程1,2
t1.start();
t2.start();
}
}
// 其中的某此运行结果如下:
当前运行的线程:线程-1, i=0
当前运行的线程:纯程-2, i=0
当前运行的线程:线程-1, i=1
当前运行的线程:纯程-2, i=1
当前运行的线程:线程-1, i=2
当前运行的线程:纯程-2, i=2
当前运行的线程:线程-1, i=3
当前运行的线程:纯程-2, i=3
当前运行的线程:线程-1, i=4
当前运行的线程:纯程-2, i=4
当前运行的线程:线程-1, i=5
当前运行的线程:纯程-2, i=5
当前运行的线程:线程-1, i=6
当前运行的线程:纯程-2, i=6
当前运行的线程:纯程-2, i=7
当前运行的线程:纯程-2, i=8
当前运行的线程:纯程-2, i=9
当前运行的线程:纯程-2, i=10
当前运行的线程:线程-1, i=7
当前运行的线程:线程-1, i=8
当前运行的线程:线程-1, i=9
当前运行的线程:线程-1, i=10
/*
结果说明, 线程-1和线程-2是交替运行
也就是说程序是采用了多线程机制运行了
Hi继承了 Thread 类,因为 Thread 类中的
setName() 和 getName()方法是定义为
final类型的,运行 start()方法来调用 run() 方法
一个线程序对象只能调用一次 start(),多次则报错
*/
// =================
通过 Runnable 接口创建线程
Runnable 定义
public interface Runnable
{
public abstract void run();
}
// 通过 Runnable 接口实现多线程
[public] class 类名 implements Runnable
{
属性;
方法;
public void run()
{
// 线程代码
}
}
// =========
public class Hi implements Runnable
{
private String name;
public Hi()
{
}
public Hi(String name)
{
setName(name);
}
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return this.name;
}
public void run()
{
for(int i=0; i<5; i++)
{
System.out.println("当前运行的线程:"+getName()+", i="+i);
}
}
public static void main(String[] args)
{
Hi r1 = new Hi("线程-1");
Hi r2 = new Hi("线程-2");
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
Thread t3 = new Thread(r1);
t1.start();
t2.start();
t3.start();
}
}
/*
当前运行的线程:线程-1, i=0
当前运行的线程:线程-1, i=1
当前运行的线程:线程-1, i=2
当前运行的线程:线程-1, i=3
当前运行的线程:线程-1, i=4
当前运行的线程:线程-1, i=0
当前运行的线程:线程-1, i=1
当前运行的线程:线程-1, i=2
当前运行的线程:线程-1, i=3
当前运行的线程:线程-1, i=4
当前运行的线程:线程-2, i=0
当前运行的线程:线程-2, i=1
当前运行的线程:线程-2, i=2
当前运行的线程:线程-2, i=3
当前运行的线程:线程-2, i=4
*/
// ============
// 在 Thread类中定义了一个类方法currentThread(),
//可利用该方法获取主线程对象的引用
public class Hi implements Runnable
{
public void run()
{
for (int i=0;i<=10 ;i++ )
{
System.out.println("当前运行的线程:"+Thread.currentThread()+", i="+i);
}
}
public static void main(String[] args)
{
// 获取主线程
Thread mt = Thread.currentThread();
System.out.println("线程信息:"+mt);
System.out.println("线程名称:"+mt.getName());
mt.setName("主线程");
System.out.println("线程名称:"+mt.getName());
Hi mThread = new Hi();
Thread t =new Thread(mThread);
t.start();
mThread.run();
}
}
/*
线程信息:Thread[main,5,main]
线程名称:main
线程名称:主线程
当前运行的线程:Thread[主线程,5,main], i=0
当前运行的线程:Thread[主线程,5,main], i=1
当前运行的线程:Thread[主线程,5,main], i=2
当前运行的线程:Thread[主线程,5,main], i=3
当前运行的线程:Thread[主线程,5,main], i=4
当前运行的线程:Thread[主线程,5,main], i=5
当前运行的线程:Thread[主线程,5,main], i=6
当前运行的线程:Thread[主线程,5,main], i=7
当前运行的线程:Thread[主线程,5,main], i=8
当前运行的线程:Thread[主线程,5,main], i=9
当前运行的线程:Thread[主线程,5,main], i=10
当前运行的线程:Thread[Thread-0,5,main], i=0
当前运行的线程:Thread[Thread-0,5,main], i=1
当前运行的线程:Thread[Thread-0,5,main], i=2
当前运行的线程:Thread[Thread-0,5,main], i=3
当前运行的线程:Thread[Thread-0,5,main], i=4
当前运行的线程:Thread[Thread-0,5,main], i=5
当前运行的线程:Thread[Thread-0,5,main], i=6
当前运行的线程:Thread[Thread-0,5,main], i=7
当前运行的线程:Thread[Thread-0,5,main], i=8
当前运行的线程:Thread[Thread-0,5,main], i=9
当前运行的线程:Thread[Thread-0,5,main], i=10
*/
// --------------
// 用 Thread 实现多线程
class Ticket extends Thread
{
private int ticket = 10;
private String name;
public Ticket(){}
public Ticket(String name)
{
setName(name);
}
public void run()
{
while (ticket > 0)
{
if (ticket > 0)
{
System.out.println(Thread.currentThread().getName()+"卖出第"+(ticket--)+"张门票");
}
}
}
}
public class Hi
{
public static void main(String[] args)
{
Ticket window1 = new Ticket("第一窗口");
Ticket window2 = new Ticket("第二窗口");
window1.start();
window2.start();
}
}
/*
第一窗口卖出第10张门票
第二窗口卖出第10张门票
第一窗口卖出第9张门票
第二窗口卖出第9张门票
第一窗口卖出第8张门票
第二窗口卖出第8张门票
第二窗口卖出第7张门票
第二窗口卖出第6张门票
第二窗口卖出第5张门票
第二窗口卖出第4张门票
第二窗口卖出第3张门票
第二窗口卖出第2张门票
第二窗口卖出第1张门票
第一窗口卖出第7张门票
第一窗口卖出第6张门票
第一窗口卖出第5张门票
第一窗口卖出第4张门票
第一窗口卖出第3张门票
第一窗口卖出第2张门票
第一窗口卖出第1张门票
*/
实现了两个线程,但没有达到各自的共享目的
// =============
// 实现了共享
class Ticket implements Runnable
{
private int ticket = 10;
public Ticket(){}
public void run()
{
while(ticket > 0)
{
if (ticket > 0)
{
System.out.println(Thread.currentThread().getName()+"卖出第"+(ticket--)+"张门票...");
}
}
}
}
public class Hi
{
public static void main(String[] args)
{
Ticket window = new Ticket();
Thread t1 = new Thread(window,"第一窗口");
Thread t2 = new Thread(window,"第二窗口");
t1.start();
t2.start();
}
}
/*
第一窗口卖出第10张门票...
第一窗口卖出第8张门票...
第一窗口卖出第7张门票...
第一窗口卖出第6张门票...
第一窗口卖出第5张门票...
第一窗口卖出第4张门票...
第一窗口卖出第3张门票...
第一窗口卖出第2张门票...
第一窗口卖出第1张门票...
第二窗口卖出第9张门票...
*/
// ------------
// 获取并设置线程的名称
//如果在创建线程时,没有显式地为其设置名称,系统会自动地为其分配一个名称,
// 一般格式为: Thread-n (n 表示从0 开始的整数)
class ThreadDemo implements Runnable
{
public void run()
{
for (int i=0; i <= 5; i++)
{
System.out.println("当前运行线程:"+Thread.currentThread().getName()+",i="+i+"活动线程的数目:"+Thread.activeCount());
}
}
}
public class Hi
{
public static void main(String[] args)
{
ThreadDemo tm = new ThreadDemo();
Thread t1 = new Thread(tm);
Thread t2 = new Thread(tm,"线程-1");
Thread t3 = new Thread(tm);
t3.setName("线程-2");
System.out.println("活动线程的数目:"+Thread.activeCount());
t1.start();
t2.start();
t3.start();
}
}
/*
活动线程的数目:1
当前运行线程:线程-2,i=0活动线程的数目:4
当前运行线程:线程-2,i=1活动线程的数目:4
当前运行线程:线程-2,i=2活动线程的数目:4
当前运行线程:线程-2,i=3活动线程的数目:4
当前运行线程:线程-2,i=4活动线程的数目:4
当前运行线程:线程-2,i=5活动线程的数目:4
当前运行线程:线程-1,i=0活动线程的数目:4
当前运行线程:线程-1,i=1活动线程的数目:3
当前运行线程:线程-1,i=2活动线程的数目:3
当前运行线程:线程-1,i=3活动线程的数目:3
当前运行线程:线程-1,i=4活动线程的数目:3
当前运行线程:线程-1,i=5活动线程的数目:3
当前运行线程:Thread-0,i=0活动线程的数目:4
当前运行线程:Thread-0,i=1活动线程的数目:2
当前运行线程:Thread-0,i=2活动线程的数目:2
当前运行线程:Thread-0,i=3活动线程的数目:2
当前运行线程:Thread-0,i=4活动线程的数目:2
当前运行线程:Thread-0,i=5活动线程的数目:2
*/
// ==================
// 线程的优先级
// 优先级从 1-10,默认为 5,用 setPriority()设置优先级
/*
优先级常量表示:
public static final int MIN_PRIORITY 线程可以具有最低优先级 1
public static final int NORM_PRIORITY 线程的默认优先级 5
public static final int MAX_PRIORIRY 线程可以具有的最高优先级 10
*/
class ThreadDemo implements Runnable
{
public void run()
{
for (int i=0; i<=5; i++)
{
System.out.println("当前运行线程:"+Thread.currentThread().getName()+", i="+i);
}
}
}
public class Hi
{
public static void main(String[] args)
{
ThreadDemo tm = new ThreadDemo();
Thread t1 = new Thread(tm, "线程-1");
Thread t2 = new Thread(tm, "线程-2");
Thread t3 = new Thread(tm,"线程-3");
Thread t4 = new Thread(tm,"线程-4");
t1.setPriority(Thread.MIN_PRIORITY);
t2.setPriority(2);
t3.setPriority(Thread.NORM_PRIORITY);
t4.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
/*
当前运行线程:线程-4, i=0
当前运行线程:线程-4, i=1
当前运行线程:线程-4, i=2
当前运行线程:线程-4, i=3
当前运行线程:线程-4, i=4
当前运行线程:线程-4, i=5
当前运行线程:线程-2, i=0
当前运行线程:线程-2, i=1
当前运行线程:线程-2, i=2
当前运行线程:线程-3, i=0
当前运行线程:线程-3, i=1
当前运行线程:线程-3, i=2
当前运行线程:线程-3, i=3
当前运行线程:线程-3, i=4
当前运行线程:线程-3, i=5
当前运行线程:线程-1, i=0
当前运行线程:线程-1, i=1
当前运行线程:线程-1, i=2
当前运行线程:线程-1, i=3
当前运行线程:线程-1, i=4
当前运行线程:线程-1, i=5
当前运行线程:线程-2, i=3
当前运行线程:线程-2, i=4
当前运行线程:线程-2, i=5
*/
// ------------------
// 让线程休眠
import java.util.Date;
class ThreadDemo implements Runnable
{
public void run()
{
for (int i=0; i<=5; i++)
{
System.out.println("当前运行线程:"+Thread.currentThread().getName()+",i="+i+",时间:"+(new Date()));
try
{
// 线程休眠 1s
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
public class Hi
{
public static void main(String[] args)
{
// 创建线程实例
ThreadDemo tm = new ThreadDemo();
// 实例化 Thread 对象 t1,2,3,并设置线程名称
Thread t1 = new Thread(tm, "线程-1");
Thread t2 = new Thread(tm,"线程-2");
Thread t3 = new Thread(tm, "线程-3");
// 启动线程
t1.start();
t2.start();
t3.start();
}
}
// ==================
// 线程的加入
import java.util.Date;
class ThreadDemo implements Runnable
{
public void run()
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
for (int i=0; i<=5; i++)
{
System.out.println("当前运行的线程名:"+Thread.currentThread().getName()+",i="+i+",时间:"+(new Date()));
}
}
}
public class Hi
{
public static void main(String[] args)
{
ThreadDemo tm = new ThreadDemo();
Thread t1 = new Thread(tm, "线程-1");
Thread main = Thread.currentThread();
t1.start();
for (int i=0; i<=5; i++)
{
if(i==3)
{
try
{
t1.join(3000);
}
catch (Exception e)
{
e.printStackTrace();
}
}
System.out.println("main="+i+"-->"+new Date());
}
}
}
/*
main=0-->Mon Feb 23 17:06:06 CST 2015
main=1-->Mon Feb 23 17:06:06 CST 2015
main=2-->Mon Feb 23 17:06:06 CST 2015
当前运行的线程名:线程-1,i=0,时间:Mon F
当前运行的线程名:线程-1,i=1,时间:Mon F
当前运行的线程名:线程-1,i=2,时间:Mon F
当前运行的线程名:线程-1,i=3,时间:Mon F
当前运行的线程名:线程-1,i=4,时间:Mon F
当前运行的线程名:线程-1,i=5,时间:Mon F
main=3-->Mon Feb 23 17:06:07 CST 2015
main=4-->Mon Feb 23 17:06:07 CST 2015
main=5-->Mon Feb 23 17:06:07 CST 2015
*/
// ----------------
// 线程的唤醒
import java.util.Date;
class ThreadDemo implements Runnable
{
public void run()
{
System.out.println("开始运行 run() 方法的时刻:"+(new Date()));
try
{
Thread.sleep(5000);
}
catch (Exception e)
{
System.out.println("线程被唤醒");
}
System.out.println("结束运行 run() 方法的时刻:"+(new Date()));
}
}
public class Hi
{
public static void main(String[] args)
{
ThreadDemo tm = new ThreadDemo();
Thread t1 = new Thread(tm, "线程-1");
t1.start();
try
{
t1.sleep(2000);
}
catch (Exception e)
{
e.printStackTrace();
}
t1.interrupt();
}
}
/*
开始运行 run() 方法的时刻:Mon Feb 23 17:32:46 CST 2015
线程被唤醒
结束运行 run() 方法的时刻:Mon Feb 23 17:32:48 CST 2015
*/
// ==================
// 后台线程
// setDaemon() 设置线程为后台线程
// isDaemon() 判断是否为后台线程
class ThreadDemo implements Runnable
{
public void run()
{
int i=0;
while(true)
{
System.out.println("i="+i++);
}
}
}
public class Hi
{
public static void main(String[] args)
{
ThreadDemo tm = new ThreadDemo();
Thread t1 = new Thread(tm, "线程-1");
t1.setDaemon(true);
if(t1.isDaemon())
{
t1.start();
}
}
}
// ------------
// 线程的礼让, yield()让出运行权
class ThreadDemo implements Runnable
{
public void run()
{
for (int i=0; i <= 10; i++)
{
System.out.println("当前运行的线程:"+Thread.currentThread().getName()+",i="+i);
Thread.currentThread().yield();
}
}
}
class ThreadDemo1 implements Runnable
{
public void run()
{
for (int i=0; i<=10; i++)
{
System.out.println("当前运行的线程:"+Thread.currentThread().getName()+",数字 i="+i);
}
}
}
public class Hi
{
public static void main(String[] args)
{
ThreadDemo tm1 = new ThreadDemo();
ThreadDemo1 tm2 = new ThreadDemo1();
Thread t1 = new Thread(tm1, "线程-1");
Thread t2 = new Thread(tm2, "线程-2");
t1.start();
t2.start();
}
}
// =================
class Ticket implements Runnable
{
private int ticket = 10;
public Ticket()
{
}
public void run()
{
while(ticket > 0)
{
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
if(ticket > 0)
{
System.out.println(Thread.currentThread().getName()+"卖出第"+(ticket--)+"张门票....");
}
}
}
}
public class Hi
{
public static void main(String[] args)
{
Ticket window = new Ticket();
Thread t1 = new Thread(window,"第一窗口");
Thread t2 = new Thread(window, "第二窗口");
t1.start();
t2.start();
}
}
/*
第一窗口卖出第10张门票....
第二窗口卖出第10张门票....
第一窗口卖出第9张门票....
第二窗口卖出第8张门票....
第一窗口卖出第7张门票....
第二窗口卖出第6张门票....
第一窗口卖出第5张门票....
第二窗口卖出第4张门票....
第一窗口卖出第3张门票....
第二窗口卖出第2张门票....
第一窗口卖出第1张门票....
*/
// 发现有重票,所以实现同步有两种方法;同步代码码头,同步方法
// ---------------
// 同步代码块
/*
synchronized (object obj)
{
// code
}
*/
class Ticket implements Runnable
{
private int ticket = 10;
public Ticket(){}
public void run()
{
while(ticket >=1)
{
synchronized(this)
{
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
if(ticket > 0)
{
System.out.println(Thread.currentThread().getName()+"卖出第"+(ticket--)+"张门票...");
}
}
}
}
}
public class Hi
{
public static void main(String[] args)
{
Ticket window = new Ticket();
Thread t1 = new Thread(window, "第一窗口");
Thread t2 = new Thread(window, "第二窗口");
t1.start();
t2.start();
}
}
/*
第一窗口卖出第10张门票...
第一窗口卖出第9张门票...
第一窗口卖出第8张门票...
第一窗口卖出第7张门票...
第一窗口卖出第6张门票...
第一窗口卖出第5张门票...
第一窗口卖出第4张门票...
第一窗口卖出第3张门票...
第一窗口卖出第2张门票...
第一窗口卖出第1张门票...
*/
// ==============
// 同步方法
/*
[访问控制符] [static | final] synchronized 返回类型 方法名(参数列表)
{
// code
}
*/
class Ticket implements Runnable
{
private int ticket = 10;
public Ticket()
{
}
public void run()
{
while(ticket > 0)
{
this.sale();
}
}
public synchronized void sale()
{
if(ticket > 0)
{
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"卖出第"+(ticket--)+"张门票...");
}
}
}
public class Hi
{
public static void main(String[] args)
{
Ticket window = new Ticket();
Thread t1 = new Thread(window, "第一窗口");
Thread t2 = new Thread(window, "第二窗口");
t1.start();
t2.start();
}
}
// ================
/*
可以通过 java.util.concurrent.locks.ReentrantLock 类对象
调用 lock(),unlock() 来实现加锁与解锁方法
*/
import java.util.concurrent.locks.*;
class Ticket implements Runnable
{
private final ReentrantLock lock = new ReentrantLock();
private int ticket = 10;
public Ticket()
{
}
public void run()
{
while(ticket > 0)
{
lock.lock();
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
if(ticket > 0)
{
System.out.println(Thread.currentThread().getName()+"卖出第"+(ticket--)+"张门票...");
}
lock.unlock();
}
}
}
public class Hi
{
public static void main(String[] args)
{
Ticket window = new Ticket();
Thread t1 = new Thread(window, "第一窗口");
Thread t2 = new Thread(window, "第二窗口");
t1.start();
t2.start();
}
}
// ==========
线程的通信沟通
notify(), notifyAll(), wait()
//唤醒等待池中的线程
public final void notify()
// 唤醒等待池中所有的线程
public final void notifyAll()
//使当前的线程等待
public final void wait() throws InterruptedException
// 使当前的线程等待,并设置最长的时间,以毫秒为单位
public final void wait(long timeout) throws InterruptedException
//使当前的线程等待时间,毫秒加纳秒
public final void wait(long timeout, int nanos) throws InterruptedException
public class Food
{
private int number = 0;
private String food = null;
public Food(){}
public Food(String Food, int number)
{
this.food = Food;
this.number = number;
}
public synchronized void setfood(int n)
{
if(this.number != 0)
{
try
{
wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
number = n;
System.out.println("放置"+this.food+"第"+this.number+"批 次");
notify();
}
public synchronized String getfood()
{
if(this.number == 0)
{
try
{
wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println("\t取走第"+this.number+"批次"+this.food);
this.number = 0;
notify();
return food+number;
}
public static void main(String[] args)
{
Food f = new Food("yes", 0);
SetFood sf = new SetFood(f);
GetFood gf = new GetFood(f);
new Thread(sf).start();
new Thread(gf).start();
}
}
public class SetFood implements Runnable
{
private Food Food;
public SetFood(Food Food)
{
this.Food = Food;
}
public void run()
{
for (int number = 1; number <= 5; number++)
{
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
Food.setfood(number);
}
}
}
public class GetFood implements Runnable
{
private Food Food;
public GetFood(Food Food)
{
this.Food = Food;
}
public void run()
{
for (int number = 1; number <= 5; number++)
{
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
Food.getfood();
}
}
}
// -----------------------