线程的创建
- 创建一个Thread类,或者一个Thread子类的对象
- 创建一个实现Runnable接口的类的对象
Thread类
Thread是一个线程类,位于java.lang包下
构造方法 | 说明 |
---|---|
Thread() | 创建一个线程对象 |
Thread(String name) | 创建一个具有指定名称的线程对象 |
Thread(Runnable target,String name) | 创建一个基于Runnable接口实现类,并且具有 指定名称的线程对象。 |
Thread类的常用方法
方法 | 说明 |
---|---|
public void run() | 线程相关的代码写在该方法中,一般需要重写 |
public void start() | 启动线程的方法 |
public static void sleep(long m) | 线程休眠m毫秒的方法 |
public void join() | 优先执行调用join()方法的线程 |
Runnable接口
- 只有一个方法run();
- Runnable是Java中用以实现线程的接口,
- 任何实现线程功能的类都必须实现该接口
线程创建
• 通过继承Thread类的方式创建线程类,重写run()方法。
class MyTherad extends Thread {//继承Thread类,创建一个新进程
public void run(){
System.out.println(getName()+"该线程正在执行!");
}
}
public class ThreadTest {
public static void main(String[] args) {
System.out.println("主线程1");
MyTherad mt = new MyTherad();
mt.start();//调用start方法启动线程
System.out.println("主线程2");
}
}
输出结果
主线程1
主线程2
Thread-0该线程正在执行!
Process finished with exit code 0
线程运行时随机的
class MyThread extends Thread{
public MyThread(String name){
super(name);
}
public void run(){//重写run方法
for(int i=1;i<=10;i++){
System.out.println(getName()+"正在运行"+i);
}
}
}
public class ThreadTest {
public static void main(String[] args) {
MyThread mt1=new MyThread("线程1");
MyThread mt2=new MyThread("线程2");
mt1.start();
mt2.start();
}
运行结果
线程2正在运行2
线程2正在运行3
线程1正在运行1
线程1正在运行2
线程1正在运行3
线程1正在运行4
线程2正在运行4
线程2正在运行5
线程2正在运行6
线程2正在运行7
线程2正在运行8
线程2正在运行9
线程2正在运行10
线程1正在运行5
线程1正在运行6
线程1正在运行7
线程1正在运行8
线程1正在运行9
线程1正在运行10
Process finished with exit code 0
• 通过实现Runnable接口的方式创建。
线程创建
为什么要实现Runnable接口?
•Java不支持多继承
•不打算重写Thread类的其他方法
class PrintRunnable implements Runnable{
//实现Runnable接口,并实现run方法
int i = 1;
@Override
public void run() {
while (i<=10)
System.out.println(Thread.currentThread().getName()+"正在运行");
}
}
public class Test {
public static void main(String[] args) {
PrintRunnable pr = new PrintRunnable();
Thread t1 = new Thread(pr);
t1.start();
//PrintRunnable pr1 = new PrintRunnable();
Thread t2 = new Thread(pr);
t2.start();
//t1,t2共享i这个资源,一共运行10次
}
}
运行结果
Thread-1正在运行2
Thread-1正在运行3
Thread-1正在运行4
Thread-1正在运行5
Thread-1正在运行6
Thread-0正在运行1
Thread-0正在运行8
Thread-1正在运行7
Thread-1正在运行10
Thread-0正在运行9
Process finished with exit code 0
线程的状态
• 新建(New)
• 可运行(Runnable)
• 正在运行(Running)
• 阻塞(Blocked)
• 终止(Dead)
sleep方法应用
• Thread类的方法
public static void sleep(long millis)
• 作用:在指定的毫秒数内让正在执行的线程休眠(暂停执行)
• 参数为休眠的时间,单位是毫秒
class MyThread implements Runnable{
@Override
public void run() {
for(int i=1;i<=30;i++){
System.out.println(Thread.currentThread().getName()+"执行第"+i+"次!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class SleepDemo {
public static void main(String[] args) {
MyThread mt=new MyThread();
Thread t=new Thread(mt);
t.start();
Thread t1=new Thread(mt);
t1.start();
}
}
join方法应用
• Thread类的方法
public final void join()
• 作用:等待调用该方法的线程结束后才能执行
• Thread类的方法
public final void join(long millis)
• 作用:等待该线程终止的最长时间为millis毫秒。
• 如果millis为0则意味着要一直等下去。
线程优先级
- Java为线程类提供了10个优先级
- 优先级可以用整数1-10表示,超过范围会抛出异常
- 主线程默认优先级为5
• 优先级常量
-MAX_PRIORITY:线程的最高优先级10
-MIN_PRIORITY:线程的最低优先级1
-NORM_PRIORITY:线程的默认优先级5
优先级相关的方法
方法 | 说明 |
---|---|
public int getPriority() | 获取线程优先级的方法 |
public void setPriority(int newPriority) | 设置线程优先级的方法 |
class MyThread extends Thread{
private String name;
public MyThread(String name){
this.name=name;
}
public void run(){
for(int i=1;i<=50;i++){
System.out.println("线程"+name+"正在运行"+i);
}
}
}
public class PriorityDemo {
public static void main(String[] args) {
//获取主线程的优先级
int mainPriority=Thread.currentThread().getPriority();
//System.out.println("主线程的优先级为:"+mainPriority);
MyThread mt1=new MyThread("线程1");
MyThread mt2=new MyThread("线程2");
//mt1.setPriority(10);
mt1.setPriority(Thread.MAX_PRIORITY);
mt2.setPriority(Thread.MIN_PRIORITY);
mt2.start();
mt1.start();
//System.out.println("线程1的优先级为:"+mt1.getPriority());
}
}
多线程运行问题
- 各个线程是通过竞争CPU时间而获得运行机会的
- 各线程什么时候得到CPU时间,占用多久,是不可预测的
- 一个正在运行着的线程在什么地方被暂停是不确定的
银行存取款问题
• 为了保证在存款或取款的时候,不允许其他线程对帐户余额进 行操作
• 需要将Bank对象进行锁定
• 使用关键字synchronized实现
同步
• synchronized关键字用在
- 成员方法
- 静态方法
- 语句块
public synchronized void saveAccount(){}
public static synchronized void saveAccount(){}
synchronized (obj){……}
package com.p04;
public class Bank {
private String account;// 账号
private int balance;// 账户余额
public Bank(String account, int balance) {
this.account = account;
this.balance = balance;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
@Override
public String toString() {
return "Bank [账号:" + account + ", 余额:" + balance + "]";
}
// 存款
public synchronized void saveAccount() {
// 获取当前的账号余额
int balance = getBalance();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 修改余额,存100元
balance += 100;
// 修改账户余额
setBalance(balance);
// 输出存款后的账户余额
System.out.println("存款后的账户余额为:" + balance);
}
public void drawAccount() {
synchronized (this) {
// 在不同的位置处添加sleep方法
// 获得当前的帐户余额
int balance = getBalance();
// 修改余额,取200
balance = balance - 200;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 修改帐户余额
setBalance(balance);
System.out.println("取款后的帐户余额:" + balance);
}
}
}
//取款
public class DrawAccount implements Runnable{
Bank bank;
public DrawAccount(Bank bank){
this.bank=bank;
}
@Override
public void run() {
bank.drawAccount();
}
}
//存款
public class SaveAccount implements Runnable{
Bank bank;
public SaveAccount(Bank bank){
this.bank=bank;
}
public void run(){
bank.saveAccount();
}
}
public class Test {
public static void main(String[] args) {
// 创建帐户,给定余额为1000
Bank bank=new Bank("1001",1000);
//创建线程对象
SaveAccount sa=new SaveAccount(bank);
DrawAccount da=new DrawAccount(bank);
Thread save=new Thread(sa);
Thread draw=new Thread(da);
save.start();
draw.start();
try {
draw.join();
save.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(bank);
}
}
输出结果
存款后的账户余额为:1100
取款后的帐户余额:900
Bank [账号:1001, 余额:900]
Prcess finished with exit code 0
线程间通信
• 问题:帐户余额不够了怎么办? • 等待存入足够的钱后处理
线程间通信
• wait()方法:中断方法的执行,使线程等待
• notify()方法:唤醒处于等待的某一个线程,使其结束等待
• nofifyAll()方法:唤醒所有处于等待的线程,使它们结束等待
public class Queue {
private int n;
boolean flag=false;
public synchronized int get() {
if(!flag){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("消费:"+n);
flag=false;//消费完毕,容器中没有数据
notifyAll();
return n;
}
public synchronized void set(int n) {
if(flag){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("生产:"+n);
this.n = n;
flag=true;//生产完毕,容器中已经有数据
notifyAll();
}
}
public class Producer implements Runnable{
Queue queue;
Producer(Queue queue){
this.queue=queue;
}
@Override
public void run() {
int i=0;
while(true){
queue.set(i++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class Consumer implements Runnable{
Queue queue;
Consumer(Queue queue){
this.queue=queue;
}
@Override
public void run() {
while(true){
queue.get();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class Test {
public static void main(String[] args) {
Queue queue=new Queue();
new Thread(new Producer(queue)).start();
new Thread(new Consumer(queue)).start();
}
}
输出结果
生产:0
消费:0
生产:1
消费:1
生产:2
消费:2
生产:3
消费:3
生产:4
消费:4
生产:5
消费:5
生产:6
消费:6
生产:7
消费:7
生产:8
消费:8
生产:9
消费:9
生产:10
消费:10
生产:11
消费:11
生产:12
消费:12
生产:13
消费:13
生产:14
消费:14
生产:15
消费:15
Process finished with exit code 1