什么是进程?每一个正在系统上运行的程序都是一个进程,是资源分配的基本单位,也是抢占处理机的调度单位。通常一个进程中包含一个或多个线程。
什么是线程?线程是程序中一个单一的顺序控制流程,与资源分配无关,它属于某一个进程,与进程内的其他线程共享进程的资源。
下面开始创建线程:
1.继承Thread类来创建线程
package thread;
public class ThreadTest1 {
public static void main(String[] args) {
Thread1 t1 = new Thread1("t1");
Thread1 t2 = new Thread1("t2");
t1.run();//只是调用run()方法,没有启动多线程
t2.start();//开启多线程方法
for(int i=0;i<60;i++){
System.out.println("main..."+i);
}
}
}
//写线程就要继承线程类Thread,并重写run()方法
class Thread1 extends Thread{
public Thread1(String name){
super(name);
System.out.println(Thread.currentThread().getName()+"创建完成");
}
//必须重写的方法,以实现自己在线程中的动作,用start()调用
public void run(){
for(int i=0;i<60;i++){
System.out.println(this.getName()+"thread..."+i);
}
}
}
2.实现Runnable接口
package thread;
public class ThreadTest2 {
public static void main(String[] args) {
Thread2 t2 = new Thread2();//创建Runnable对象
Thread t = new Thread(t2);//在创建线程时,加入Runnable对象
t.start();//开启线程
//为了区分Thread2线程,给主线程添加些内容
for(int i=0;i<60;i++){
System.out.println("main..."+i);
}
}
}
//线程也可以通过实现Runnable接口,重写run()方法
class Thread2 implements Runnable{
//重写Run()方法,以实现自己在线程中的动作,用start()调用
public void run(){
for(int i=0;i<60;i++){
System.out.println(Thread.currentThread().getName()+"thread..."+i);
}
}
}
这两种方式都可以成功创建线程,但还是推荐第二种方式,因为java是单继承的语言,也就是说一旦继承了Thread类,就无法在继承其他的类,这样不利于代码的灵活性。多线程可以通过锁(synchronized)来控制让其交替运行:
package thread;
/**
* 多线程交替运行,同步锁
* @author asus
*冻结线程wait(), 唤醒等待线程notify(), 唤醒所有等待线程notifyall()
*/
public class InputOutputDemo {
public static void main(String[] args) {
Ren r = new Ren();
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}
//封装对象
class Ren{
String name = null;
String sex = null;
boolean flag = false;
}
//输入
class Input implements Runnable{
private Ren r;
//创建Input对象时获取共有资源
Input(Ren r){
this.r = r;
}
public void run(){
int b = 0;
//使用while循环不断地存入数据
while(true){
//同步锁,使存入和输出同步
synchronized(r){
//标志位,true表示完成存入数据,false表示完成输出数据
if(r.flag){
try {
r.wait();//冻结线程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//根据b值的不同存入不同的数据
if(b==0){
r.name = "A";
r.sex = "male";
}else{
r.name = "B";
r.sex = "female";
}
b=(b+1)%2;
r.flag = true;
r.notify();//唤醒等待线程
}
}
}
}
//输出
class Output implements Runnable{
private Ren r;
//创建Output对象时获取共有资源
Output(Ren r){
this.r = r;
}
public void run(){
//使用while循环不断地存入数据
while(true){
//同步锁,使存入和输出同步
synchronized(r){
//标志位,true表示完成存入数据,false表示完成输出数据
if(!r.flag){
try {
r.wait();//冻结线程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(r.name+"..."+r.sex);
r.flag = false;
r.notify();//唤醒等待线程
}
}
}
}
当然多个同步锁有时候也会造成死锁package thread;
/**
* 这是一个死锁程序:当线程中含有多个锁的时候,就有可能出现死锁现象,即每一个线程持有对方的锁且不被释放
* @author asus
*
*/
public class LockDemo {
public static void main(String[] args) {
//创建对象并传入标志位
Lock l1 = new Lock(true);
Lock l2 = new Lock(false);
//创建线程
Thread t1 = new Thread(l1);
Thread t2 = new Thread(l2);
//开启线程
t1.start();
t2.start();
}
}
//提供锁对象
class MyLock{
static Object lockA = new Object();
static Object lockB = new Object();
}
//多线程死锁
class Lock implements Runnable {
private boolean flag;
Lock(boolean flag) {
this.flag = flag;
}
//当两个或多个线程持有对方同步锁并且不释放,就会出现死锁现象
public void run() {
if(flag){
//使用A锁同步
synchronized(MyLock.lockA){
System.out.println("if A");
//使用B锁同步
synchronized(MyLock.lockB){
System.out.println("if B");
}
}
}else{
//使用B锁同步
synchronized(MyLock.lockB){
System.out.println("else A");
//使用A锁同步
synchronized(MyLock.lockA){
System.out.println("else B");
}
}
}
}
}