进程与多线程的概念,在如今高并发的数据操作环境中已经深入人心。那进程的概念与多线程的概念很多计算机的学习者却知之甚少,那就先让我们来了解以下进程与多线程的概念吧。
什么是进程,举个例子,就是运行在计算机上的一段程序,是系统进行资源分配和调度的一个基本单位。当你打开windows系统中的任务管理器,查看当前运行进程时,那些正在你电脑上使用资源,占用内存,使用CPU的程序就是一个个进程。
什么时线程呢?线程时进程内部的子单位,一个进程中会有一个到多个线程去执行自己的任务,这些线程进行并发操作,恪尽职守,共同完成进程所正在执行的任务。举个例子,如果你打开QQ这个应用程序,这就是一个进程,而随之需要的聊天功能,传输数据功能,加载图片功能,听歌看视频等功能,就是一个个线程正在操作和执行的。线程之间执行并发操作,其实是微观串行,宏观并行,因为每一个线程需要使用CPU时,总是只有一个线程在占用CPU,其他线程在后面等待,由于一些内部处理的机制和切换时间短,人根本察觉不到这样的切换状态,所以会感觉线程之间都是并行操作,其实是串行操作。
那系统为什么要进行多线程并发,而不是单线程操作呢?比方说,任务1和任务2完全独立,互不相关,任务1是在等待y
远程服务器返回数据,以便进行后期的处理,这时CPU一直处于等待状态,一直在空运行。如果任务2是在10秒之后被运行,虽然执行任务2的时间非常短,仅仅是1秒,但也必须在任务1运行结束后才可以运行任务2,这样做,CPU的利用率会非常低。而如果是多线程并发,CPU完全可以在任务1和任务2之间来回切换,使任务2不必等到10秒再运行。这样系统的运行效率大大得到提升。
使用多线程,就必须掌握多线程的代码操作:
一:继承Thread类
package com.mythread.www;
public class MyThread extends Thread{
public void run() {
try {
for(int i=0;i<10;i++) {
int time = (int)(Math.random()*1000);
Thread.sleep(time);
System.out.println("run="+Thread.currentThread().getName());
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
package test;
import com.mythread.www.MyThread;
public class Run {
public static void main(String[]args) {
try {
MyThread thread = new MyThread();
thread.setName("myThread");
thread.start();
for(int i=0;i<10;i++) {
int time = (int)(Math.random()*1000);
Thread.sleep(time);
System.out.println("main="+Thread.currentThread().getName());
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
由于线程执行的随机性,主线程和MyThread线程的打印顺序很随机。
二:实现Runnable接口
package myrunnable;
public class MyRunnable implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("运行中!");
}
}
package test;
import com.mythread.www.MyThread;
import myrunnable.MyRunnable;
public class Run {
public static void main(String[]args) {
Runnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
System.out.println("运行结束!");
}
}
介绍完以上多线程实例运行的代码操作,现在让我们来学习一下线程之间的共享数据和不共享数据,以及所造成的非线程安全问题。
首先来说一下数据不共享的情况:
一个线程类中的内部属性,由这个线程类新创建出来的线程,不共享这个内部属性数据。
package com.mythread.www;
public class MyThread extends Thread{
private int count=5;
public MyThread(String name) {
super();
this.setName(name);
}
public void run() {
super.run();
while(count>0) {
count--;
System.out.println("由 "+this.currentThread().getName()+" 计算,count="+count);
}
}
}
package test;
import com.mythread.www.MyThread;
import myrunnable.MyRunnable;
public class Run {
public static void main(String[]args) {
MyThread a = new MyThread("A");
MyThread b = new MyThread("B");
MyThread c = new MyThread("C");
a.start();
b.start();
c.start();
}
}
再来说一下数据共享的情况:
package com.mythread.www;
public class MyThread extends Thread{
private int count=5;
public void run() {
super.run();
count--;
System.out.println("由 "+this.currentThread().getName()+" 计算,count="+count);
}
}
package test;
import com.mythread.www.MyThread;
import myrunnable.MyRunnable;
public class Run {
public static void main(String[]args) {
MyThread mythread = new MyThread();
Thread a = new Thread(mythread,"A");
Thread b = new Thread(mythread,"B");
Thread c = new Thread(mythread,"C");
Thread d = new Thread(mythread,"D");
Thread e = new Thread(mythread,"E");
a.start();
b.start();
c.start();
d.start();
e.start();
}
}
可是在这段代码中产生了 (由A计算,count=3) (由B计算,count=3)的异常状态,这就叫做非线程安全状态。需要在线程类中的run方法前面加一个synchronized同步锁。这样就是一个临界区,每次只有一个线程可以在临界区中运行,运行完毕后其他线程才能进去。所以很好的解决的非线程安全的问题。