1程序(program)是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。
2、什么是进程(process)
进程(process)是程序的一次执行过程,或是正常运行的一个程序。是一个动态的过程: 有它自身的产生、存在和消亡的过程
3、什么是线程(thread)
进程可进一步细化为线程,是一个程序内部的一条执行路径
二、进程和线程的区别 1、从属关系不同进程是正在运行程序的实例,进程中包含了线程 线程不能包含进程
2、描述侧重点不同进程是操作系统分配资源的基本单位,而线程是操作系统调度的基本单位
3、共享资源不同多个进程间不能共享资源,每个进程有自己的堆、栈、虚存空间、文件描述符等信息, 而线程可以共享进程资源文件。
4、上下文切换速度不同线程上下文切换速度快(上下文切换指的是:从一个进程切换到另一个进程),进程上下文切换速度慢
5、操作者不同一般情况下,进程的操作者是操作系统,而线程的操作者是编程人员
三、多线程中继承Thread类常用的方法四、线程的生命周期 新建:
thread类的子类的对象被声明并创建时,新生的线程对象处于被创建状态。
就绪:处于新建状态的线程被start()后,将进入线程队列等待CPU时间片,此时它已具备了运行条件,只是还没分配到CPU资源。
运行:当就绪的线程被调度,并且获得CPU资源时,便进入运行状态
阻塞:在某种特殊情况下,被人为挂起或者执行输入输出操作时,让出CPU并临时终止自己的行为,进入阻塞状态
死亡:线程完成了它的全部工作或线程提前被强制性的终止或出现异常导致结束。
五、创建多线程的方式—>>代码实现 1、继承thread类(方式一)写法(一)
package com.gaokangxiang.thread;
public class MyThread03 {
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
Demo01 demo01 = new Demo01();
Demo02 demo02 = new Demo02();
demo01.start();
demo02.start();
}
}
class Demo01 extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
class Demo02 extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 != 0) {
System.out.println(Thread.currentThread().getName() + ":" +i);
}
}
}
}
2、写法(二)
package com.gaokangxiang.thread;
public class MyThread04 {
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
// 创建thread类的匿名子类
new Thread() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}.start();
new Thread() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 != 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}.start();
}
}
2、修改线程的名字
package com.gaokangxiang.thread;
public class MyThread07 extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
// 修改线程的名字
Thread.currentThread().setName("主线程");
System.out.println(Thread.currentThread().getName());
MyThread07 myThread07 = new MyThread07();
myThread07.setName("子线程");
myThread07.start();
}
}
3、线程中断
package com.gaokangxiang.thread;
public class MyThread08 extends Thread{
@Override
public void run() {
for (int i = 0; i < 30; i++) {
try {
if (i == 20) {
// 进程中断
Thread.currentThread().interrupt();
}
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + "--" + i);
} catch (InterruptedException e) {
return;
}
}
}
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
MyThread08 myThread08 = new MyThread08();
myThread08.start();
}
}
2、实现Runnable接口(方式二)
package com.gaokangxiang.runnable;
public class MyRunnable01 implements Runnable {
@Override
public void run() {
// 遍历100以内的偶数
for (int i = 0; i < 100; i++) {
if (i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
// 创建实现类的对象
MyRunnable01 myRunnable = new MyRunnable01();
// 将此对象作为参数传递到Thread类构造器中,创建Thread类的对象
Thread thread01 = new Thread(myRunnable);
// 在启动一个线程
Thread thread02 = new Thread(myRunnable);
// 修改名字
thread01.setName("线程一");
// 通过Thread类的对象调用start方法
thread01.start();
// 修改名字
thread02.setName("线程二");
// 通过Thread类的对象调用start方法
thread02.start();
}
}
3、实现Runnable接口—>>解决线程安全问题< 一 >
package com.gaokangxiang.runnable;
public class MyRunnable02 implements Runnable {
private int ticket = 100;
// 创建一个同步监视器
Object obj = new Object();
@Override
public void run() {
while (true) {
synchronized (obj) { // synchronized (MyRunnable02.class)
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + ":票号为--" + ticket);
ticket--;
} else {
break;
}
}
}
}
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
MyRunnable02 myRunnable02 = new MyRunnable02();
Thread thread01 = new Thread(myRunnable02);
thread01.setName("窗口一");
thread01.start();
Thread thread02 = new Thread(myRunnable02);
thread02.setName("窗口二");
thread02.start();
Thread thread03 = new Thread(myRunnable02);
thread03.setName("窗口三");
thread03.start();
}
}
4、实现Runnable接口—>>解决线程安全问题< 二 >
package com.gaokangxiang.runnable;
public class MyRunnable03 implements Runnable {
private int ticket = 100;
@Override
public void run() {
while (true) {
show();
}
}
// 同步方法synchronized 它的同步监视器就是:this
private synchronized void show(){
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + ":票号为--" + ticket);
ticket--;
}
}
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
MyRunnable03 myRunnable03 = new MyRunnable03();
Thread thread01 = new Thread(myRunnable03);
thread01.setName("窗口一");
thread01.start();
Thread thread02 = new Thread(myRunnable03);
thread02.setName("窗口二");
thread02.start();
Thread thread03 = new Thread(myRunnable03);
thread03.setName("窗口三");
thread03.start();
}
}
5、实现Runnable接口—>>解决线程安全问题< 三 >
package com.gaokangxiang.runnable;
import java.util.concurrent.locks.ReentrantLock;
public class MyRunnable05 implements Runnable{
private int ticket = 100;
private ReentrantLock lock = new ReentrantLock(true);
@Override
public void run() {
while (true){
// 将需要被同步的代码块放入try结构中,finally结尾
try {
// 调用锁定的lock方法,保证只有一个线程进入
lock.lock();
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":卖票,票号为---" + ticket);
ticket--;
} else {
break;
}
} finally {
// 调用解锁的方法unlock
lock.unlock();
}
}
}
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
MyRunnable05 myRunnable05 = new MyRunnable05();
Thread thread01 = new Thread(myRunnable05);
Thread thread02 = new Thread(myRunnable05);
Thread thread03 = new Thread(myRunnable05);
thread01.setName("窗口一");
thread02.setName("窗口二");
thread03.setName("窗口三");
thread01.start();
thread02.start();
thread03.start();
}
}
6、演示线程的死锁问题
package com.gaokangxiang.runnable;
public class MyRunnable04 {
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer();
StringBuffer s2 = new StringBuffer();
// 创建thread类的匿名子类
new Thread() {
@Override
public void run() {
synchronized (s1) {
s1.append("a");
s2.append(1);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s2) {
s1.append("b");
s1.append(2);
}
}
}
}.start();
new Thread() {
@Override
public void run() {
synchronized (s2) {
s1.append("c");
s1.append(3);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s1) {
s1.append("d");
s1.append(4);
}
}
}
}.start();
}
}
7、关于线程通信的例子
package com.gaokangxiang.runnable;
public class MyRunnable06 implements Runnable {
private int num = 1;
@Override
public void run() {
while (true) {
synchronized (this) {
notify();
if (num <= 100) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + num);
num++;
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
}
}
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
MyRunnable06 myRunnable06 = new MyRunnable06();
Thread thread01 = new Thread(myRunnable06);
Thread thread02 = new Thread(myRunnable06);
thread01.setName("线程一");
thread02.setName("线程二");
thread01.start();
thread02.start();
}
}
8、关于多线程的练习
package com.gaokangxiang.runnable;
public class MyRunnable07 {
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
Clerk clerk = new Clerk();
Producer producer = new Producer(clerk);
Consume consume = new Consume(clerk);
producer.setName("生产者一");
producer.start();
consume.setName("消费者一");
consume.start();
}
}
class Clerk {
private int num = 0;
// 生产产品
public synchronized void produceProducer() {
if (num < 20) {
num++;
System.out.println(Thread.currentThread().getName() + ": 开始生产第" +
num + "个产品");
notify();
} else {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 消费产品
public synchronized void consumeProducer() {
if (num > 0) {
System.out.println(Thread.currentThread().getName() + ": 开始消费第" +
num + "个产品");
num--;
notify();
} else {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Producer extends Thread { // 生产者
private Clerk clerk;
public Producer(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
System.out.println(getName() + ": 开始生产产品---");
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.produceProducer();
}
}
}
class Consume extends Thread { // 消费者
private Clerk clerk;
public Consume(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ": 开始消费产品---");
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.consumeProducer(); // 调用consumeProducer()
}
}
}
9、创建多线程的方式三—>>实现Callable接口
注:这是JDK5.0后新增的创建多线程的方式
package com.gaokangxiang.callable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class MyCallable implements Callable {
@Override
public Object call() throws Exception {
int num = 0;
for (int i = 0; i < 100; i++) {
if (i % 2 ==0){
System.out.println(i);
num += i;
}
}
return num;
}
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
MyCallable myCallable = new MyCallable();
FutureTask futureTask = new FutureTask(myCallable);
new Thread(futureTask).start();
try {
// get方法返回值是FutureTask构造器参数Callable实现类重写的Call方法的返回值
Object num = futureTask.get();
System.out.println(num);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
10、创建多线程的方式四—>>使用线程池
1、背景
经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大。
2、思路
提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。
使用线程池的好处
➢提高响应速度[ (减少门创建新线程的时间)
➢降低资源消耗(重复利用线程池中线程,不需要每次都创建)
➢便于线程管理
corePoolSize: 核心池的大小
maximumPoolSize:最大线程数
keepAliveTime: 线程没有任务时最多保持多长时间后会终止
代码实现:
package com.gaokangxiang.threadpool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class MyThreadPool01 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
}
}
class MyThreadPool02 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 != 0) {
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
}
}
public class MyThreadPool {
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
// 1、提供指定线程数量的线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
// 2、执行指定的线程的操作。需要提供实现Runnable接口或Callable接口实现类的对象
pool.execute(new MyThreadPool01());// 适合适用于Runnable
pool.execute(new MyThreadPool02());// 适合适用于Runnable
//pool.submit();适用于callable接口
// 关闭连接池
pool.shutdown();
}
}



