多线程入门(自我记录)

一、线程与进程的区别:

1.进程:
1)进程就是一个应用程序(虚拟机就是java在操作系统上的运行程序,就是java.exe);一个进程中可以包含一个或多个线程.
2)每个进程都有独立的代码和数据空间,进程的切换会有很大的开销

2.线程:
1)一个程序内部中的顺序控制流(左手画圆,右手画方是不是就是一种多线程呢?).
2)同一类线程共享代码和数据空间,每个线程有独立运行的栈和程序计数器,线程切换的开销小.

Java中分为main线程和主线程.(其实还有一个隐藏的线程,即垃圾回收线程)

3.线程的生命周期:
在这里插入图片描述

二、多线程实现的两种方式
1.继承Thread类

package test;

//1.继承Thread类
public class Thread1 extends Thread {
	//2.重写run方法
	@Override
	public void run() {
		for(int i=1;i<=50;i++) {
			System.out.println("我是线程中的第"+i+"个i");
		}
	}
	
	public static void main(String[] args) {
		Thread1 thread1 = new Thread1();
		//这里注意,开启线程使用默认方法start(),而不要写run()方法;
		//3.执行start方法启动线程
		thread1.start();
		for(int i=1;i<=50;i++) {
			System.out.println("我是main中的第"+i+"个i");
		}
	}
}

2.实现Runnable接口

package test;

public class RunAbleDemo implements Runnable {
	
	private int count = 50;
	//重写run方法
	@Override
	public void run() {
		while(count>0) {
			//Thread.currentThread()指当前运行中的线程
			System.out.println("第"+count+"号已被"+Thread.currentThread().getName()+"售出");
			count--; 
		}
	}
	public static void main(String[] args) {
		RunAbleDemo runAbleDemo = new RunAbleDemo();
		//传入实现Runnable接口的类的对象,以及线程名称????(不是很明白)
		Thread t1 = new Thread(runAbleDemo,"线程1");
		Thread t2 = new Thread(runAbleDemo,"线程2");
		//设置优先级优先级越高,执行几率越大,并不是必定是优先级高的线程一定会第一个执行完.
		t1.setPriority(Thread.MAX_PRIORITY);
		t2.setPriority(Thread.MIN_PRIORITY);
		t1.start();
		t2.start();
	} 
	
}

接下来是我目前见到的一些方法的使用
1.Thread.sleep(long millis);
让线程中止一段时间,在睡眠期满的瞬间,再次调用该线程不一定会恢复他的执行

package test;

public class ThreadSleep extends Thread {
	@Override
	public void run() {
		for(int i=1;i<=50;i++) {
			System.out.println(i);
			//此处的异常不能抛出,只能try-catch因为Thread没有抛出异常,所以这里也不行!
			try {
				//一般情况下单位都是毫秒,线程休眠1S(每1S执行一次??)
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) {
		ThreadSleep sleep = new ThreadSleep();
		sleep.start();
	}
	
}

2.join();使当前线程等待,知道调用这个join方法的线程终止
AThread:

@Override
	public void run() {
		for(int i=1;i<=50;i++) {
			System.out.println("我是第"+i+"个AThread");
		}
	}

BThread:

@Override
	public void run() {
		for(int i=1;i<=50;i++) {
			System.out.println("我是第"+i+"个BThread");
		}
	}

MainThread:

package thread;

public class MainThread {
	public static void main(String[] args) throws InterruptedException {
		System.out.println("Main线程开始运行了!");
		AThread aThread = new AThread();
		BThread bThread = new BThread();
		aThread.start();
		bThread.start();
		//记得异常是join()方法抛出的~~
		aThread.join();
		bThread.join();
		System.out.println("Main线程结束运行了!");
	}
}

三、线程同步
有时两个或多个线程可能会试图同时访问同一个资源,为了确保在任何时间点一个共享的资源只能被一个线程使用,就使用了同步这一概念.

同步代码块和同步方法代码:

package thread;

public class synchroThread implements Runnable {

	private int count = 100;

	@Override
	public void run() {
		while (count() > 0) {
			// 同步代码块 this 指当前对象
			synchronized (this) {
				//这里处理了如果上一个线程在睡眠状态,导致没有count--  下一个线程已经进来执行了,此时的count为1,所以会出现卖出第0号或负号
				if (count > 0) {
					System.out.println("第" + count + "号票已经被" + Thread.currentThread().getName() + "售出");
					// 测试设置睡眠才能出现上述的那种错误
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					count--;
				}
			}
		}
	}

	// 同步方法
	public synchronized int count() {
		return count;
	}

	public static void main(String[] args) {
		synchroThread synchroThread = new synchroThread();
		Thread t1 = new Thread(synchroThread, "窗口1");
		Thread t2 = new Thread(synchroThread, "窗口2");
		Thread t3 = new Thread(synchroThread, "窗口3");
		Thread t4 = new Thread(synchroThread, "窗口4");
		Thread t5 = new Thread(synchroThread, "窗口5");
		Thread t6 = new Thread(synchroThread, "窗口6");
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
		t6.start();
	}
}

注意事项:受到synchronized保护的程序代码块和方法中,要访问的对象属性必须设定为private,因为如果不设定为private,那么就可以用不同的方式来访问他,这样就达不到保护的作用了

synchronized方法
优点:
1)可以显示的知道哪些方法是被synchronized关键字保护的
缺点:
1)方法中有些内容是不需要同步的,如果该方法执行会花很长时间,那么其他人就要花较多的时间等待锁被归还
2)只能取得自己对象的锁,有时候程序设计的需求,可能会需要取得其他对象的锁.

synchronized代码块
优点:
1)可以针对某段程序代码同步,不需要浪费时间在别的程序代码上.
2)可以取得不同对象的锁
缺点:
1)无法显示的得知哪些方法是被synchronized关键字保护的.

四、死锁
1.两个线程,彼此在等待对方占据的锁
2.锁的归还几种方式:

  • 基本上执行完同步的程序代码后,锁就会自动归还.
  • 用break语句跳出同步的语句块,不过这对于写在方法声明的synchronized没有作用;
  • 遇到return语句;
  • 遇到了异常;

简易死锁代码:
DeadLockThread1:

package thread;

public class DeadLockThread1 extends Thread {
	private Object locka;
	private Object lockb;
	
	public DeadLockThread1(Object locka, Object lockb) {
		this.locka = locka;
		this.lockb = lockb;
	}

	@Override
	public void run() {
		System.out.println("DeadLockThread1开始执行");
		synchronized (locka) {
			System.out.println("locka已被DeadLockThread1线程锁住");
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			synchronized (lockb) {
				System.out.println("lockb已被DeadLockThread1线程锁住");
			}
		}
	}
}

DeadLockThread2:

package thread;

public class DeadLockThread2 extends Thread {
	private Object locka;
	private Object lockb;
	
	public DeadLockThread2(Object locka, Object lockb) {
		this.locka = locka;
		this.lockb = lockb;
	}
	
	@Override
	public void run() {
		System.out.println("DeadLockThread2开始执行");
		synchronized (lockb) {
			System.out.println("lockb已被DeadLockThread2线程锁住");
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			synchronized (locka) {
				System.out.println("locka已被DeadLockThread2线程锁住");
			}
		}
	}
}

测试一下死锁程序:
DeadLockTest:

package thread;

public class DeadLockTest {
	static Object locka = new Object();
	static Object lockb = new Object();
	public static void main(String[] args) {
		DeadLockThread1 dThread1 = new DeadLockThread1(locka, lockb);
		DeadLockThread2 dThread2 = new DeadLockThread2(locka, lockb);
		dThread1.start();
		dThread2.start();
	}
}

我还是一个刚刚入门的萌新,
这篇文章也只是我用来记录自己学习过程的第一步…如果有什么不对的地方还请前辈,大佬们指出,让我提前改正,万分感谢.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值