进程的概念:
线程的概念:
Thread类和Runnable接口介绍:
进程的创建:
Thread介绍:
Thread的常用方法:
Runnable接口:
线程创建:
通过Thread类创建线程:
测试代码1:
package com.imooc.thread;
//创建一个新的线程
class MyThread extends Thread {
public void run() {
System.out.println(getName() + "该线程正在执行!");
}
}
public class ThreadTest {
public static void main(String[] args) {
System.out.println("主线程1");
MyThread mt = new MyThread();
// 启动线程
// 线程只能执行一次
mt.start();
System.out.println("主线程2");
}
}
输出结果:
主线程1
主线程2
Thread-0该线程正在执行!
测试代码2:
package com.imooc.thread1;
//创建线程类
class MyThread extends Thread{
public MyThread(String name) {
super(name);
}
public void 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();
}
}
输出结果是随机的,由于对于时间片的分配是随机的
输出结果1:
线程1正在运行第1次
线程2正在运行第1次
线程1正在运行第2次
线程2正在运行第2次
线程1正在运行第3次
线程2正在运行第3次
线程1正在运行第4次
线程2正在运行第4次
线程1正在运行第5次
线程1正在运行第6次
线程1正在运行第7次
线程1正在运行第8次
线程1正在运行第9次
线程1正在运行第10次
线程2正在运行第5次
线程2正在运行第6次
线程2正在运行第7次
线程2正在运行第8次
线程2正在运行第9次
线程2正在运行第10次
输出结果2:
线程1正在运行第1次
线程2正在运行第1次
线程1正在运行第2次
线程2正在运行第2次
线程1正在运行第3次
线程2正在运行第3次
线程1正在运行第4次
线程2正在运行第4次
线程1正在运行第5次
线程2正在运行第5次
线程1正在运行第6次
线程1正在运行第7次
线程1正在运行第8次
线程2正在运行第6次
线程1正在运行第9次
线程2正在运行第7次
线程2正在运行第8次
线程1正在运行第10次
线程2正在运行第9次
线程2正在运行第10次
通过实现Runnable接口创建线程:
测试代码:
package com.imooc.runnable;
class PrintRunnable implements Runnable {
// 类内代码可以共享
int i = 1;
@Override
public void run() {
while (i <= 10)
System.out.println(Thread.currentThread().getName() + "正在运行" + (i++));
}
}
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();
}
}
输出结果是随机的
输出结果1:
Thread-0正在运行1
Thread-1正在运行2
Thread-1正在运行4
Thread-0正在运行3
Thread-1正在运行5
Thread-0正在运行6
Thread-0正在运行8
Thread-0正在运行9
Thread-1正在运行7
Thread-0正在运行10
输出结果:
Thread-0正在运行1
Thread-1正在运行1
Thread-0正在运行2
Thread-1正在运行3
Thread-0正在运行4
Thread-1正在运行5
Thread-0正在运行6
Thread-1正在运行7
Thread-0正在运行8
Thread-1正在运行9
Thread-0正在运行10
Runnable接口的实现顺序:
编程练习:
1、通过实现Runnable接口的方式创建线程类Cat和Dog,run()方法实现的功能为:加入一个循环长度为3的for循环,分别循环输出信息“A cat”和“A dog”。
2、在测试类中分别创建Cat和Dog类的对象,启动两个线程。
3、在测试类中创建一个循环长度为3的for循环,打印输出信息“main thread”。
测试代码:
Cat类:
package test017;
class Cat implements Runnable {
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + "A cat");
}
}
}
Dog类:
package test017;
class Dog implements Runnable {
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + "A dog");
}
}
}
测试类:
package test017;
public class ThreadTest {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
System.out.println("main thread");
}
Cat one = new Cat();
Dog two = new Dog();
Thread t1 = new Thread(one);
Thread t2 = new Thread(two);
t1.start();
t2.start();
}
}
输出结果:
main thread
main thread
main thread
Thread-0A cat
Thread-0A cat
Thread-0A cat
Thread-1A dog
Thread-1A dog
Thread-1A dog
线程的状态和生命周期:
线程的状态:
线程的生命周期:
sleep方法的使用:
测试代码:sleep( )方法在调用时需要捕获一个中断异常
package com.imooc.sleep;
class MyThread implements Runnable {
public void run() {
for (int i = 1; i <= 15; i++) {
System.out.println(Thread.currentThread().getName() + "正在运行" + "第" + i + "次");
try {
// 休眠1000ms以后,重新变成可运行状态,等待获取cpu的使用权
//sleep( )方法在调用时需要捕获一个中断异常
Thread.sleep(1);
} 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();
}
}
输出结果:
在线程1休眠的时候,线程2更可能获得cpu的使用权,然后就是线程2休眠,线程1更可能获得cpu的使用权,因此会出现依次交替饿结果
Thread-0正在运行第1次
Thread-1正在运行第1次
Thread-1正在运行第2次
Thread-0正在运行第2次
Thread-1正在运行第3次
Thread-0正在运行第3次
Thread-1正在运行第4次
Thread-0正在运行第4次
Thread-1正在运行第5次
Thread-0正在运行第5次
Thread-1正在运行第6次
Thread-0正在运行第6次
Thread-1正在运行第7次
Thread-0正在运行第7次
Thread-1正在运行第8次
Thread-0正在运行第8次
Thread-1正在运行第9次
Thread-0正在运行第9次
Thread-1正在运行第10次
Thread-0正在运行第10次
Thread-0正在运行第11次
Thread-1正在运行第11次
Thread-1正在运行第12次
Thread-0正在运行第12次
Thread-1正在运行第13次
Thread-0正在运行第13次
Thread-1正在运行第14次
Thread-0正在运行第14次
Thread-0正在运行第15次
Thread-1正在运行第15次
编程练习:
Letter类:
package test018;
class Letter implements Runnable {
char[] letter = new char[26];
public Letter() {
for (int i = 0; i <= 25; i++) {
letter[i] = (char) (i + 97);
}
}
public void run() {
Letter chars = new Letter();
for (int i = 0; i <= 25; i++) {
System.out.print(chars.letter[i] + " ");
try {
// 休眠1000ms以后,重新变成可运行状态,等待获取cpu的使用权
// sleep( )方法在调用时需要捕获一个中断异常
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
LetterTest类:
package test018;
public class Test {
public static void main(String[] args) {
Letter one = new Letter();
Thread t = new Thread(one);
t.start();
}
}
输出结果:
a b c d e f g h i j k l m n o p q r s t u v w x y z
join方法的使用:
测试:
在不使用join方法的时候:
package com.imooc.join;
class MyThread extends Thread {
public void run() {
for (int i = 1; i < 21; i++) {
System.out.println(getName() + "正在执行" + i + "次");
}
}
}
public class JoinDemo {
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
// try {
// mt.join();
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
for (int i = 1; i < 21; i++) {
System.out.println("主进程" + "正在执行" + i + "次");
}
}
}
输出结果:随机输出,
Thread-0正在执行1次
Thread-0正在执行2次
主进程正在执行1次
Thread-0正在执行3次
Thread-0正在执行4次
Thread-0正在执行5次
Thread-0正在执行6次
Thread-0正在执行7次
Thread-0正在执行8次
Thread-0正在执行9次
Thread-0正在执行10次
Thread-0正在执行11次
Thread-0正在执行12次
Thread-0正在执行13次
Thread-0正在执行14次
Thread-0正在执行15次
Thread-0正在执行16次
Thread-0正在执行17次
Thread-0正在执行18次
Thread-0正在执行19次
Thread-0正在执行20次
主进程正在执行2次
主进程正在执行3次
主进程正在执行4次
主进程正在执行5次
主进程正在执行6次
主进程正在执行7次
主进程正在执行8次
主进程正在执行9次
主进程正在执行10次
主进程正在执行11次
主进程正在执行12次
主进程正在执行13次
主进程正在执行14次
主进程正在执行15次
主进程正在执行16次
主进程正在执行17次
主进程正在执行18次
主进程正在执行19次
主进程正在执行20次
加入join后代码:有可能会出现异常,所以就要捕获异常
package com.imooc.join;
class MyThread extends Thread {
public void run() {
for (int i = 1; i < 21; i++) {
System.out.println(getName() + "正在执行" + i + "次");
}
}
}
public class JoinDemo {
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
try {
mt.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int i = 1; i < 21; i++) {
System.out.println("主进程" + "正在执行" + i + "次");
}
}
}
输出结果:调用join后,会先执行Thread-0
Thread-0正在执行1次
Thread-0正在执行2次
Thread-0正在执行3次
Thread-0正在执行4次
Thread-0正在执行5次
Thread-0正在执行6次
Thread-0正在执行7次
Thread-0正在执行8次
Thread-0正在执行9次
Thread-0正在执行10次
Thread-0正在执行11次
Thread-0正在执行12次
Thread-0正在执行13次
Thread-0正在执行14次
Thread-0正在执行15次
Thread-0正在执行16次
Thread-0正在执行17次
Thread-0正在执行18次
Thread-0正在执行19次
Thread-0正在执行20次
主进程正在执行1次
主进程正在执行2次
主进程正在执行3次
主进程正在执行4次
主进程正在执行5次
主进程正在执行6次
主进程正在执行7次
主进程正在执行8次
主进程正在执行9次
主进程正在执行10次
主进程正在执行11次
主进程正在执行12次
主进程正在执行13次
主进程正在执行14次
主进程正在执行15次
主进程正在执行16次
主进程正在执行17次
主进程正在执行18次
主进程正在执行19次
主进程正在执行20次
在join(millis)里添加时间参数:
测试代码:
package com.imooc.join;
class MyThread extends Thread {
public void run() {
for (int i = 1; i < 2000; i++) {
System.out.println(getName() + "正在执行" + i + "次");
}
}
}
public class JoinDemo {
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
try {
mt.join(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int i = 1; i < 21; i++) {
System.out.println("主进程" + "正在执行" + i + "次");
}
}
}
输出结果:会在运行1毫秒之后,让出cpu给其他进程
线程的优先级:
测试代码:
package com.imooc.priority;
class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
public void run() {
for (int i = 1; i <= 10; i++) {
System.out.println("线程正在运行" + name + " " + i);
}
}
}
public class Priority {
public static void main(String[] args) {
// 获取主线程优先级
int mainPriority = Thread.currentThread().getPriority();
System.out.println("主线程的优先级:" + mainPriority);
MyThread mt1 = new MyThread("线程XXX");
mt1.setPriority(1);
mt1.start();
System.out.println("线程XXX的优先级:" + mt1.getPriority());
MyThread mt = new MyThread("线程SSS");
// mt.setPriority(10);
mt.setPriority(Thread.MAX_PRIORITY);
mt.start();
System.out.println("线程SSS的优先级:" + mt.getPriority());
}
}
输出结果:
虽然优先级高,但是也并不能保证可以优先执行,具体情况具体分析
主线程的优先级:5
线程XXX的优先级:1
线程SSS的优先级:10
线程正在运行线程XXX 1
线程正在运行线程XXX 2
线程正在运行线程SSS 1
线程正在运行线程XXX 3
线程正在运行线程XXX 4
线程正在运行线程XXX 5
线程正在运行线程XXX 6
线程正在运行线程XXX 7
线程正在运行线程XXX 8
线程正在运行线程XXX 9
线程正在运行线程XXX 10
线程正在运行线程SSS 2
线程正在运行线程SSS 3
线程正在运行线程SSS 4
线程正在运行线程SSS 5
线程正在运行线程SSS 6
线程正在运行线程SSS 7
线程正在运行线程SSS 8
线程正在运行线程SSS 9
线程正在运行线程SSS 10
线程同步:
synchronized关键字保证共享对象在同一时刻只能被一个线程访问,但它不能保证多个线程可以同时执行和结束
案例:
Bank类:
package com.imooc.bank;
public class Bank {
private String account;// 账号
private int balance;// 账户余额
// 无参构造
public Bank() {
}
// 带参构造
public Bank(String account, int balance) {
this.account = account;
this.balance = balance;
}
// setter getter
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;
}
// 重写toString()
@Override
public String toString() {
return "Bank [账号:" + account + ", 余额:" + balance + "]";
}
// 存款,加上synchronized,保证执行这个的线程不允许被打断
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) {
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);
}
}
}
SaveAccount类:
package com.imooc.bank;
public class SaveAccount implements Runnable {
Bank bank;
public SaveAccount(Bank bank) {
this.bank = bank;
}
@Override
public void run() {
bank.saveAccount();
}
}
DrawAccount类:
package com.imooc.bank;
public class DrawAccount implements Runnable {
Bank bank;
public DrawAccount(Bank bank) {
this.bank = bank;
}
@Override
public void run() {
bank.drawAccount();
}
}
测试代码:
package com.imooc.bank;
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]
线程间通信:
案例:生产者消费者
Queue类:
package com.imooc.queue;
public class Queue {
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();//唤醒所有线程,结束死锁
}
}
Producer类:
package com.imooc.queue;
public class Producer implements Runnable{
Queue queue;
public 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();
}
}
}
}
Consumer类:
package com.imooc.queue;
public class Consumer implements Runnable{
Queue queue;
public 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();
}
}
}
}
测试代码:
package com.imooc.queue;
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
总结: