目录
- 进程和多线程的概念以及线程的优点
- 1.进程概念
- 2.线程概念
- 3.优点
- 使用多线程
- 1.继承Thread类
- 代码运行和代码执行和调用顺序无关
- 线程调用的随机性
- 执行start方法的顺序不代表线程启动顺序
- 2.实现Runnable接口
- 3.实例变量与线程安全
- (1)不共享数据的情况
- (2)共享数据的情况
- 线程安全问题案例1
- 线程安全问题2
- 留意i--和system.out.println()异常
- 案例演示
- 4.currentThread()方法
- 1.案例1
- 2.案例2:
- 5.isAlive()方法
- 6.sleep()方法
- 6.getId()方法
- 7.停止线程
- 1)停不了的线程
- 2.判断线程是否是停止状态
- interrupted
- 如何是main中断线程
- isInterrupted
- 3)能停止的线程-异常法
- 问题:
- 解决
- 4).在沉睡中停止
- 5)暴力停止stop()
- 6)方法stop()与java.lang.ThreadDeath异常
- 7)释放锁的不良后果
- 8)使用return停止线程
- 8 暂停线程
- a.suspend和resume的使用
- b.suspend和resume方法的缺点--独占
- 实验1:
- 还有一种独占锁的情况
- c.suspend和resume方法的缺点--不同步
- 9.yiled
- 10.线程的优先级
- 1)线程优先级的继承性
- 2)优先级具有规则性
- 3)优先级具有随机性
- 4)看谁运行快
- 11.守护线程
进程和多线程的概念以及线程的优点
1.进程概念
2.线程概念
3.优点
使用多线程
接触下线程
public class Demo1 {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
}
}
1.继承Thread类
代码运行和代码执行和调用顺序无关
自定义一个线程类:
public class MyThread extends Thread{
@Override
public void run() {
super.run();
System.out.println("Mythead");
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
System.out.println("运行结束!");
}
}
线程调用的随机性
public class RandomThread extends Thread {
@Override
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();
}
}
public static void main(String[] args) {
try {
RandomThread randomThread = new RandomThread();
randomThread.setName("myThread");
randomThread.start();
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();
}
System.out.println("run==" + Thread.currentThread().getName());
}
}
执行start方法的顺序不代表线程启动顺序
public class ThreadDemo extends Thread{
private int i;
public ThreadDemo(int i){
super();
this.i = i;
}
@Override
public void run() {
System.out.println(i);
}
public static void main(String[] args) {
ThreadDemo t1 = new ThreadDemo(1);
ThreadDemo t2 = new ThreadDemo(2);
ThreadDemo t3 = new ThreadDemo(3);
ThreadDemo t4 = new ThreadDemo(4);
ThreadDemo t5 = new ThreadDemo(5);
ThreadDemo t6 = new ThreadDemo(6);
ThreadDemo t7 = new ThreadDemo(7);
ThreadDemo t8 = new ThreadDemo(8);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
t8.start();
}
}
2.实现Runnable接口
如何使用Runable类呢?
public class Run {
public static void main(String[] args) {
MyRunable myRunable = new MyRunable();
Thread thread = new Thread(myRunable);
thread.start();
System.out.println("运行结束");
}
}
3.实例变量与线程安全
(1)不共享数据的情况
public class MyThread extends Thread {
private int count=5;
public MyThread(String name) {
super();
this.setName(name);
}
@Override
public void run() {
super.run();
while(count > 0){
count --;
System.out.println("由 " + this.currentThread().getName() + " 计算,count=" + count);
}
}
}
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();
}
}
(2)共享数据的情况
线程安全问题案例1
测试项目
public class MyThread extends Thread{
private int count=5;
@Override
public void run() {
// super.run();
// while(count > 0){
count --;
System.out.println("由 " + this.currentThread().getName() + " 计算,count=" + count);
// }
}
}
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();
}
}
运行结果:
结果:每次都不一样。
案例:
public class MyThread extends Thread {
private int count = 5;
@Override
synchronized public void run() {
count--;
System.out.println("由 " + this.currentThread().getName() + " 计算,count=" + count);
}
}
线程安全问题2
public class LoginServlet {
private static String usernameRef;
private static String passwordRef;
public static void doPost(String username, String password){
try {
usernameRef = username;
if(username.equals("a")){
Thread.sleep(5000);
}
passwordRef = password;
System.out.println("username=" + usernameRef + " password="+passwordRef);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
public class Alogin extends Thread{
@Override
public void run() {
LoginServlet.doPost("a", "aa");
}
}
public class Blogin extends Thread {
@Override
public void run() {
LoginServlet.doPost("b", "bb");
}
}
public class Run {
public static void main(String[] args) {
Alogin a = new Alogin();
a.start();
Blogin b = new Blogin();
b.start();
}
}
也出现了线程安全问题。
解决方式,也是加上 synchronized
synchronized public static void doPost(String username, String password){
留意i–和system.out.println()异常
案例演示
public class MyThread extends Thread {
private int i = 5;
@Override
public void run() {
System.out.println("i=" + (i--)+ " threadName=" + Thread.currentThread().getName());
//注意: 代码i--由前面项目中单独一行运行改成在当前项目中在println()方法中直接进行打印
}
public static void main(String[] args) {
MyThread run = new MyThread();
Thread t1 = new Thread(run);
Thread t2 = new Thread(run);
Thread t3 = new Thread(run);
Thread t4 = new Thread(run);
Thread t5 = new Thread(run);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
为了防止发生非线程安全问题,还是应该继续使用同步方法。
4.currentThread()方法
该方法返回代码段正在被哪个线程调用的信息。
1.案例1
public class MyThread extends Thread{
public MyThread() {
System.out.println("构造方法的打印: "+ Thread.currentThread().getName());
}
@Override
public void run() {
System.out.println("run构造方法的打印: "+ Thread.currentThread().getName());
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
}
}
改下:
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.run();
}
均被main主线程所调用。
2.案例2:
public class CountOperate extends Thread{
public CountOperate() {
System.out.println("countOpera---begin");
System.out.println("Thread.currentThread.getName()=" + Thread.currentThread().getName());
System.out.println("this.getName()==" + this.getName());
System.out.println("countOpera---end");
}
@Override
public void run() {
System.out.println("countOpera---begin");
System.out.println("Thread.currentThread.getName()=" + Thread.currentThread().getName());
System.out.println("this.getName()==" + this.getName());
System.out.println("countOpera---end");
}
public static void main(String[] args) {
CountOperate c = new CountOperate();
Thread t1 = new Thread(c);
t1.setName("A");
t1.start();
}
}
5.isAlive()方法
判断当前的线程是否是活跃的状态
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("begin==" + this.isAlive());
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
System.out.println("begin==" + myThread.isAlive());
myThread.start();
System.out.println("end==" + myThread.isAlive());
}
}
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
System.out.println("begin==" + myThread.isAlive());
myThread.start();
Thread.sleep(1000);
System.out.println("end==" + myThread.isAlive());
}
6.sleep()方法
public class MyThread extends Thread {
@Override
public void run() {
try {
System.out.println("run threadName="+this.currentThread().getName() + " begin");
Thread.sleep(2000);
System.out.println("run threadName="+this.currentThread().getName() + " end");
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
System.out.println("begin = " + System.currentTimeMillis());
myThread.start();
System.out.println("end = " + System.currentTimeMillis());
}
}
修改实验
public static void main(String[] args) {
MyThread myThread = new MyThread();
System.out.println("begin = " + System.currentTimeMillis());
myThread.run();
System.out.println("end = " + System.currentTimeMillis());
}
6.getId()方法
public static void main(String[] args) {
Thread thread = Thread.currentThread();
System.out.println(thread.getId() + "====" + thread.getName());
}
当前线程的id为1,名字为main。
7.停止线程
这里的停止的概念很容易混淆,看着这本书这段的时候,看的快睡着了,太绕了,没看进去,不过听了首歌<灌篮高手的主题曲>又看了一遍,明白了,哈哈。
1)停不了的线程
public class MyThread extends Thread {
@Override
public void run() {
super.run();
for (int i=0;i<5000;i++){
System.out.println("i=="+(i+1));
}
}
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(1000);
thread.interrupt();
}
}
调用interrupt(),线程没停止。咋停止啊。我也想知道,往下看。
2.判断线程是否是停止状态
interrupted
public class MyThread extends Thread {
@Override
public void run() {
super.run();
for (int i=0;i<5000;i++){
System.out.println("i=="+(i+1));
}
}
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(1000);
thread.interrupt();
//Thread.currentThread().interrupt();
System.out.println(" 是否停止1? = " + thread.interrupted());
System.out.println(" 是否停止2? = " + thread.interrupted());
System.out.println("end");
}
}
如何是main中断线程
当前只调用Thread了,里面没有别的线程的时候,他是static的方法。
public static void main(String[] args) {
Thread.currentThread().interrupt();
System.out.println("是否停止1: " + Thread.interrupted());
System.out.println("是否停止1: " + Thread.interrupted());
System.out.println("end");
}
isInterrupted
public class MyThread extends Thread {
@Override
public void run() {
super.run();
for (int i = 0; i < 5000; i++) {
System.out.println("i==" + (i + 1));
}
}
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(1000);
thread.interrupt();
System.out.println(" 是否停止1? = " + thread.isInterrupted());
System.out.println(" 是否停止2? = " + thread.isInterrupted());
System.out.println("end");
}
}
这是我的结果,书上是
奇怪啊,目前也不知道为啥
3)能停止的线程-异常法
问题:
public class MyThread extends Thread {
@Override
public void run() {
super.run();
for (int i=0;i<500000;i++){
if(this.isInterrupted()){
System.out.println("已经是停止状态了,我要退出了。");
break;
}
System.out.println("i="+(i+1));
}
System.out.println(" 我被输出, 如果此代码是for又继续运行,线程并未停止!");
}
}
public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(2000);
thread.interrupt();
}
}
解决
public class MyThread extends Thread {
@Override
public void run() {
super.run();
try{
for (int i=0;i<500000;i++){
if(this.isInterrupted()){
System.out.println("已经是停止状态了,我要退出了。");
throw new InterruptedException(); //异常方法解决这个问题
}
System.out.println("i="+(i+1));
}
}catch (InterruptedException e){
System.out.println(" 进MyThread.java类run方法中的catch了!");
e.printStackTrace();
}
}
}
4).在沉睡中停止
public class MyThread extends Thread{
@Override
public void run() {
super.run();
try {
System.out.println("run begin");
Thread.sleep(200000);
System.out.println("run end");
}catch (Exception e){
System.out.println("在沉睡中被停止!进入catch!"+this.isInterrupted());
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
try {
MyThread myThread = new MyThread();
myThread.start();
Thread.sleep(2000);
myThread.interrupt();
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
}
}
如果在main测试方法中去掉sleep呢
去掉sleep的实验
public class MyThread extends Thread{
@Override
public void run() {
super.run();
try {
for (int i=0;i<100000;i++){
System.out.println("i="+(i+1));
}
System.out.println("run begin");
Thread.sleep(200000);
System.out.println("run end");
}catch (Exception e){
System.out.println("先停止,再遇到了sleep!进入catch!"+this.isInterrupted());
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
// Thread.sleep(2000);
myThread.interrupt();
System.out.println("end");
}
}
5)暴力停止stop()
public class MyThread extends Thread {
private int i =0;
@Override
public void run() {
try {
while(true){
i++;
System.out.println("i=" + i);
Thread.sleep(1000);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) throws InterruptedException {
System.out.println(11);
MyThread thread = new MyThread();
thread.start();
Thread.sleep(8000);
thread.stop();
}
}
6)方法stop()与java.lang.ThreadDeath异常
public class Mythread extends Thread {
@Override
public void run() {
try {
this.stop();
}catch (ThreadDeath e){
System.out.println("进入了catch方法");
e.printStackTrace();
}
}
public static void main(String[] args) {
Mythread thread = new Mythread();
thread.start();
}
}
7)释放锁的不良后果
public class SynchronizedObject {
private String username = "a";
private String password = "aa";
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
synchronized public void printString(String username, String password){
try {
this.username = username;
System.out.println("22222");
Thread.sleep(100000);
this.password = password;
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
public class MyThread extends Thread {
private SynchronizedObject object;
public MyThread(SynchronizedObject object) {
this.object = object;
}
@Override
public void run() {
System.out.println(3333);
object.printString("b", "bb");
}
}
public class Run {
public static void main(String[] args) {
try{
SynchronizedObject synchronizedObject = new SynchronizedObject();
MyThread myThread = new MyThread(synchronizedObject);
myThread.start();
System.out.println("111111");
myThread.sleep(500);
System.out.println(synchronizedObject.getUsername()+" "+synchronizedObject.getPassword());
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
强制stop操作数据不一样。
8)使用return停止线程
public class MyThread extends Thread {
@Override
public void run() {
while(true){
if(this.isInterrupted()){
System.out.println("停止了!");
return;
}
System.out.println("timer=="+System.currentTimeMillis());
}
}
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
System.out.println(11111);
Thread.sleep(1);
thread.interrupt();
}
}
8 暂停线程
a.suspend和resume的使用
public class MyThread extends Thread {
private int i;
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
@Override
public void run() {
while (true) {
i++;
}
}
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
System.out.println("2222222222");
Thread.sleep(5000);
//A段
thread.suspend();
System.out.println("A==" + System.currentTimeMillis() + " i=" + thread.getI());
Thread.sleep(5000);
System.out.println("A==" + System.currentTimeMillis() + " i=" + thread.getI());
//B段
thread.resume();
Thread.sleep(5000);
//c段
thread.suspend();
System.out.println("B==" + System.currentTimeMillis() + " i=" + thread.getI());
Thread.sleep(5000);
System.out.println("B==" + System.currentTimeMillis() + " i=" + thread.getI());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
b.suspend和resume方法的缺点–独占
实验1:
public class SynchronizedObject {
synchronized public void pringString(){
System.out.println("begin");
if(Thread.currentThread().getName().equals("a")){
System.out.println("a线程永远 suspend 了");
Thread.currentThread().suspend();
}
System.out.println("end");
}
public static void main(String[] args) {
try {
final SynchronizedObject object = new SynchronizedObject();
Thread thread1 = new Thread(){
@Override
public void run() {
object.pringString();
}
};
thread1.setName("a");
thread1.start();
Thread.sleep(1000);
Thread thread2= new Thread(){
@Override
public void run() {
System.out.println("thread2启动了,但进入不了pringString方法,只打印1个begin");
System.out.println("因为pringString()方法被a线程锁定并且永远suspend暂停了");
}
};
thread2.start();
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
还有一种独占锁的情况
public class MyThread extends Thread {
private long i = 0;
@Override
public void run() {
while(true){
i++;
// System.out.println(i);
}
}
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(1000);
thread.suspend();
System.out.println("main end");
}
}
这里打没问题,但是,加一行代码
结果显示:根本停不下来!!!
c.suspend和resume方法的缺点–不同步
public class MyObject {
private String username = "1";
private String password = "11";
public void setValue(String u, String p){
this.username = u;
if(Thread.currentThread().getName().equals("a")){
System.out.println("停止a线程");
Thread.currentThread().suspend();
}
this.password = p;
}
public void printUseranamePassword(){
System.out.println(username + " " + password );
}
public static void main(String[] args) throws InterruptedException {
final MyObject myObject = new MyObject();
Thread thread1 = new Thread(){
@Override
public void run() {
myObject.setValue("a", "aa");
}
};
thread1.setName("a");
thread1.start();
Thread.sleep(500);
Thread thread2 = new Thread(){
@Override
public void run() {
myObject.printUseranamePassword();
}
};
thread2.start();
}
}
9.yiled
public class MyThread extends Thread {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
int count = 0;
for (int i = 0; i < 5000000; i++) {
//Thread.yield();
count = count + (i + 1);
}
long endTime = System.currentTimeMillis();
System.out.println("用时: " + (endTime - beginTime) + "毫秒");
}
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
运行结果:
放开Thread.yield();
结果:
10.线程的优先级
1)线程优先级的继承性
public class Run {
public static void main(String[] args) {
System.out.println("main thread begin priority=" + Thread.currentThread().getPriority());
// Thread.currentThread().setPriority(6);
System.out.println("main thread end priority=" + Thread.currentThread().getPriority());
MyThread1 thread1 = new MyThread1();
thread1.start();
}
}
运行结果:
打开Thread.currentThread().setPriority(6)
,
运行结果:
2)优先级具有规则性
public class MyThread1 extends Thread {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
long addResult = 0;
for (int j = 0; j < 10; j++) {
for (int i = 0; i < 50000; i++) {
Random random = new Random();
random.nextInt();
addResult = addResult + i;
}
}
long enTime = System.currentTimeMillis();
System.out.println("1111111===" + (enTime - beginTime));
}
}
public class MyThread2 extends Thread {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
long addResult = 0;
for (int j = 0; j < 10; j++) {
for (int i = 0; i < 50000; i++) {
Random random = new Random();
random.nextInt();
addResult = addResult + i;
}
}
long enTime = System.currentTimeMillis();
System.out.println("22222===" + (enTime - beginTime));
}
}
public class Run {
public static void main(String[] args) {
for(int i=0;i<5;i++){
MyThread2 thread2 = new MyThread2();
thread2.setPriority(1);
thread2.start();
MyThread1 thread1 = new MyThread1();
thread1.setPriority(10);
thread1.start();
}
}
}
运行结果:
3)优先级具有随机性
import java.util.Random;
public class MyThread1 extends Thread {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
Random random = new Random();
random.nextInt();
}
long enTime = System.currentTimeMillis();
System.out.println("1111111===" + (enTime - beginTime));
}
}
import java.util.Random;
public class MyThread2 extends Thread {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
Random random = new Random();
random.nextInt();
}
long enTime = System.currentTimeMillis();
System.out.println("22222===" + (enTime - beginTime));
}
}
public class Run {
public static void main(String[] args) {
for(int i=0;i<5;i++){
MyThread2 thread2 = new MyThread2();
thread2.setPriority(5);
thread2.start();
MyThread1 thread1 = new MyThread1();
thread1.setPriority(6);
thread1.start();
}
}
}
4)看谁运行快
public class MyThread1 extends Thread{
private int count = 0;
public int getCount() {
return count;
}
@Override
public void run() {
while(true){
count++;
}
}
}
public class MyThread2 extends Thread {
private int count = 0;
public int getCount() {
return count;
}
@Override
public void run() {
while (true){
count++;
}
}
}
public class Run {
public static void main(String[] args) {
try {
MyThread1 myThread1 = new MyThread1();
myThread1.setPriority(Thread.NORM_PRIORITY - 3);
myThread1.start();
MyThread2 myThread2 = new MyThread2();
myThread2.setPriority(Thread.NORM_PRIORITY + 3);
myThread2.start();
Thread.sleep(2000);
myThread1.stop();
myThread2.stop();
System.out.println("myThread1==" + myThread1.getCount());
System.out.println("myThread2==" + myThread2.getCount());
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
此实验证明:优先级高运行的快。
11.守护线程
public class MyThread extends Thread {
private int i = 0;
@Override
public void run() {
try {
while (true){
i++;
System.out.println("i=" + i);
Thread.sleep(1000);
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
MyThread myThread = new MyThread();
myThread.setDaemon(true);
myThread.start();
Thread.sleep(5000);
System.out.println("我离开thread对象也不再打印了,也就是停止了!!");
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
守护线程也退出了。
至此,多线程入门第一步完了,下一篇文章要了解synchronized的运用!!