多线程的使用
四种多线程的创建,线程通信,同步
程序,进程,线程概念
程序
程序是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。
进程
进程是程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程:有它自身的产生、存在和消亡的过程。——生命周期。
线程
进程可进一步细化为线程,是一个程序内部的一条执行路径。
多线程
多线程就是多个线程同时运行或交替运行。单核CPU的话是顺序执行,也就是交替运行。多核CPU的话,因为每个CPU有自己的运算器,所以在多个CPU中可以同时运行。
理解同步、异步,并发、并行
同步和异步
同步和异步通常用来形容一次方法调用。
同步:同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为。
异步:异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者可以继续后续的操作。
并发和并行
并行:多个CPU同时执行多个任务
并发:一个CPU(采用时间片)同时执行多个任务
多线程创建
继承Thread
package thread;
/**
* 创建多线程 方式一:
* 1.创建一个继承于Thread的子类
* 2.重写Thread中的run()方法
* 3.创建继承于Thread子类的对象
* 4.通过对象调用Thread中的star()方法
* @author LJW
*
* 遍历50以内数字
*/
/*
* 创建一个继承于Thread的子类
*/
class MyThread extends Thread {
// 重写Thread中的run()方法
@Override
public void run() {
for(int i = 1; i < 50; i++) {
System.out.println(i);
}
}
}
public class ThreadTest {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
for(int i = 1; i < 50; i++) {
System.out.println(i + "***********");
}
}
}
实现Runnable接口
package thread;
/**
* 创建多线程 方式二:
* 1.创建实现Runnable接口的实现类
* 2.重写静态方法run()
* 3.创建实现类的对象
* 4.通过Thread类的构造器,创建对象
* 5.调用star()方法
* @author LJW
*
*/
class RunnableThread implements Runnable{
@Override
public void run() {
for(int i = 1; i < 50; i++) {
System.out.println(Thread.currentThread().getName() + ":" +i);
}
}
}
public class TestThread {
public static void main(String[] args) {
RunnableThread runnableThread = new RunnableThread();
Thread thread = new Thread(runnableThread);
thread.setName("线程一");
thread.start();
}
}
实现Callable接口
package thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/*
*求1-10之和
*/
class AddNum implements Callable{
private int num = 10;
int sum = 0;
@Override
public Object call() throws Exception {
for (int i = 1; i <= 10; i++) {
sum += i;
}
return sum;
}
}
public class CallableTest {
public static void main(String[] args) {
AddNum addNum = new AddNum();
FutureTask futureTask = new FutureTask(addNum);
new Thread(futureTask).start();
try {
//获取Callable实现类中call()方法返回值
Object sum = futureTask.get();
System.out.println(sum);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
线程池创建
package thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class PrintNum implements Runnable{
@Override
public void run() {
for(int i = 1; i <= 10; i++) {
System.out.println(i);
}
}
}
public class ThreadPool {
public static void main(String[] args) {
//创建指定数量的线程池
ExecutorService service = Executors.newFixedThreadPool(10);
//执行指定线程操作
//适用于Runnable
service.execute(new PrintNum());
//适用于Callable
// service.submit(task);
//关闭连接池
service.shutdown();
}
}
Thread类的有关方法
1.start():启动线程,执行对象的run()方法。
2.run():线程在被调度时执行的操作。
3.currentThread():返回当前线程。
4.currentThread().getName():获取当前线程名。
5.sleep():放弃对当前CPU的控制,使得线程进入阻塞状态。
6.join():a,b两线程,若a.join(),则当a线程执行完后执行b线程。
7.yield():线程让步,暂停当前正在执行的线程,把执行机会让给优先级相同或更高的线程。
8.stop():强制线程生命期结束,不推荐使用。
9.isAlive():返回boolean,判断线程是否还活着。
线程生命周期
线程同步
synchronized代码块实现
package thread;
import org.junit.Test;
class Window implements Runnable{
private int ticket = 60;
Object o = new Object();
@Override
public void run() {
while(true) {
synchronized(o) { //o为同步监视器,要保证唯一。
if(ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "票号为: " + ticket);
ticket--;
}
else {
break;
}
}
}
}
}
/**
* 单元测试多线程要注意最后使用sleep()使得输出结果补全
* @author LJW
*
*/
public class TestProcess {
@Test
public void testThread() {
Window window = new Window();
Thread t1 = new Thread(window);
Thread t2 = new Thread(window);
Thread t3 = new Thread(window);
t1.start();
t2.start();
t3.start();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
Window window = new Window();
Thread t1 = new Thread(window);
Thread t2 = new Thread(window);
Thread t3 = new Thread(window);
t1.start();
t2.start();
t3.start();
}
}
synchronized方法实现
package thread;
class Window1 extends Thread {
private static int ticket = 100;
@Override
public void run() {
while(true) {
if(ticket <= 0) {
break;
}
sale();
}
}
public static synchronized void sale() { //同步监视器为:Window.class
if(ticket > 0) {
//睡眠100毫秒
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "票号为: " + ticket);
ticket--;
}
}
}
public class TestProcess1 {
public static void main(String[] args) {
Window1 w1 = new Window1();
Window1 w2 = new Window1();
Window1 w3 = new Window1();
w1.setName("窗口一");
w2.setName("窗口二");
w3.setName("窗口三");
w1.start();
w2.start();
w3.start();
}
}
创建ReentrantLock对象锁
package thread;
import java.util.concurrent.locks.ReentrantLock;
class Window2 implements Runnable{
private int ticket = 100;
private ReentrantLock reen = new ReentrantLock();
@Override
public void run() {
while(true) {
//开启锁
reen.lock();
if(ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "票号为: " + ticket);
ticket--;
}
else {
break;
}
//解锁
reen.unlock();
}
}
}
public class TestProcess2 {
public static void main(String[] args) {
Window2 w = new Window2();
Thread t1 = new Thread(w);
Thread t2 = new Thread(w);
Thread t3 = new Thread(w);
t1.setName("线程1");
t2.setName("线程2");
t3.setName("线程3");
t1.start();
t2.start();
t3.start();
}
}
线程通信
package thread;
/**
* 三个线程 交替打印1-60
* @author LJW
*
*/
class Print implements Runnable{
private int number = 1;
@Override
public void run() {
while(true) {
synchronized(this) {
//唤醒所有的wait()
notifyAll();
if(number <= 60) {
System.out.println(Thread.currentThread().getName() + " : " + number);
number++;
try {
//线程进入阻塞,会释放同步监听器
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
break;
}
}
}
}
}
public class ConmunicationTest {
public static void main(String[] args) {
Print p = new Print();
Thread t1 = new Thread(p);
Thread t2 = new Thread(p);
Thread t3 = new Thread(p);
t1.setName("线程1");
t2.setName("线程2");
t3.setName("线程3");
t1.start();
t2.start();
t3.start();
}
}
经典生产者消费者问题
package thread;
class Clerk{
private int productNum = 0;
//生产产品
public synchronized void produceProduct() {
if(productNum < 20) {
productNum++;
System.out.println(Thread.currentThread().getName() + "生产产品,产品剩余 : " + productNum);
notify();
}
else {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//消费产品
public synchronized void consumProduct() {
if(productNum > 0) {
productNum--;
System.out.println(Thread.currentThread().getName() + "消费产品,产品剩余 : " + productNum);
notify();
}
else {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//生产者
class Producer extends Thread{
private Clerk clerk;
public Producer(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
clerk.produceProduct();
}
}
}
//消费者
class Consumer extends Thread{
private Clerk clerk;
public Consumer(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
clerk.consumProduct();
}
}
}
public class ProductTest {
public static void main(String[] args) {
Clerk clerk = new Clerk();
Producer producer = new Producer(clerk);
Consumer consumer = new Consumer(clerk);
producer.setName("生产者");
consumer.setName("消费者");
producer.start();
consumer.start();
}
}