首页 > 代码库 > 线程操作

线程操作

线程的实现:
方法:
1 继承Thread类
2 实现Runnable 接口

案例1:
class Thread1 extends Thread{
//run 就是不需要等待的方法 线程方法
public void run() {
try {
for (int i = 0; i <22; i++) {
System.out.println("子线程+"+i);
//休眠 (cpu 马上就会走)
Thread.sleep(1000);

if(i==5){
System.out.println("请输入");
Scanner in=new Scanner(System.in);
System.out.println(in.next());
}

}
} catch (Exception e) {
e.printStackTrace();
}
}
}


public class MyThread01 {
public static void main(String[] args) throws Exception {
//main 函数实际是主线程
//创建一个线程
Thread1 th1=new Thread1();
th1.setPriority(10);//最高优先级
//获得当前线程 设置优先级
Thread.currentThread().setPriority(1);
//点火
th1.start();//启动线程 //run 就会被执行
for (int i = 0; i <20; i++) {
System.out.println("~~~主线程+"+i);


//休眠
Thread.sleep(800);//到底谁在sleep
if(i==18){
th1.join(); //等待th1 结束 然后再执行
}
}
}

}
分析:
1.线程是进程中的不同的执行路径,多个线程可以同时并发进行,但线程之间有优先级,主线程的优先级高于其他线程 例:main函数的当前线程
2.从时间上看线程之间的执行类似于交替执行的过程,只是计算机处理时间过短,使得看上去像同时执行
3.


案例2:
//接口的作用只是限制方法名
class Thread02 implements Runnable{
public void run() {
try {
for (int i = 0; i <1000; i++) {
System.out.println("子线程+"+i);
//休眠 (cpu 马上就会走)
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

public class MyThread2 {
public static void main(String[] args) throws Exception {
//并不是创建一个线程
Thread02 th2=new Thread02();
//创建一个线程
Thread th1=new Thread(th2);
th1.start();
for (int i = 0; i <1000; i++) {
System.out.println("~~~主线程+"+i);
//休眠
Thread.sleep(1000);
}
}

}


线程安全:
//线程安全问题 当多个线程 访问执行修改 同一个资源的时候
//那就会有线程安全问题 (称为线程不安全的)
//同步 记住单词
1.struts1 是单实例 多线程的 表单数据必须要分开
分析:多线程之间在进程中共享数据,共享数据容易引发安全问题 2.struts2 是多实例 单线程的
分析:多实例之间对于用户的各种请求处理互不影响

总结:
在一次运行活动下,我们可以根据事物的客观自然来选择程序的执行特点。

例:servlet 单实例 多线程

案例1:
class SellPiao implements Runnable{
int i=20;
public void run() {
while(true){
synchronized (SellPiao.class) { //同步代码块 线程安全的
if(i<=0){
break;
}
int temp=i;
System.out.println("收钱");
i=temp-1;
System.out.println("已经售出第"+i+"张票");

}
}
}
}
//线程安全的代价就效率降低了..所以尽量不要 使用多线程修改公共的变量

public class MyThread03 {
public static void main(String[] args) {
SellPiao sp=new SellPiao();

Thread t1=new Thread(sp);
t1.start();
Thread t2=new Thread(sp);
t2.start();
}
//同步方法 这个方法一次只能进一个线程
//同步一定要确定 同一个人守门
public synchronized void say(){

}
}

认知:
1.synchronized 修饰同步的方法
分析:
1)同步的方法,保证了只有一个线程能进同步方法,同步是能进行数据共享的一种表现形式(每个线程都可以操作的数据),所以同步必须保证数据是共有的(同一个人守门)
2)在一个对象中如果方法中都有synchronized,而没有wait的方法出现时,只能是一个线程访问。如果对象中没有synchronized修饰或者有wait方法出现则可以有其他线程访问
总结:
同步可以保证线程的安全,实现同步必须保证数据共享(同一个人守门),synchronized修饰


2.th1.suspend(); //不安全
分析:线程暂停,但仍被挂起,持有之前获得的锁定,其他线程无法访问锁定资源,当其他线程等待被“挂起”的线程又试图使用其他一个锁定的资源,造成死锁

解决:
1)标识:在Thread中设置一个标识,当标识指定线程活动时用notify重新启动线程,当标识指定线程应该挂起时用wait命其进入等待状态

th1.resume(); //恢复
3.th1.stop(); //不安全
分析:强制停止线程,解除线程获取的所有锁定,当对象处于不连贯的状态时,其他线程能在那种状态下检查和修改它们,很难检查问题所在

 

案例2:
public class MyThread04 {
//有肯能同步 也 实际就是使用this 守门
public synchronized void say() {
try {
System.out.println("读书");
Thread.sleep(1);
System.out.println("看书");
} catch (Exception e) {
e.printStackTrace();
}
}
//使用的是静态守门人 肯定同步了
public static synchronized void say2() {
try {
System.out.println("读书");
Thread.sleep(1);
System.out.println("看书");
} catch (Exception e) {
e.printStackTrace();
}
}


public static void main(String[] args) {
//可以确定是 静态方法肯定同步了
//匿名内部类 来写线程
final MyThread04 mt=new MyThread04();

new Thread(){
public void run() {
mt.say();
}
}.start();

new Thread(){
public void run() {
mt.say();
}
}.start();

}

}

 

线程:
public class Test {
//编程写出 4个人线程 对同一个变量++ --
static int i=0;
public static void main(String[] args) {
Test t=new Test();
// t.wait(); //等待
// t.notify(); //唤醒

new Thread(){
public void run() {
while(true){
i++;
System.out.println(i);
}
};
}.start();

new Thread(){
public void run() {
while(true){
i++;
System.out.println(i);
}
};
}.start();

new Thread(){
public void run() {
while(true){
i--;
System.out.println(i);
}
};
}.start();

new Thread(){
public void run() {
while(true){
i--;
System.out.println(i);
}
};
}.start();
}

}

 

进程:
基本概念:进程是一块包含了某些资源的内存区域。操作系统利用进程把它的工作划分为一些功能单元
基本内涵:进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,也是系统进行资源分配和调度的独立单位

 

线程:
进程中所包含的一个活多个执行单元
执行线索
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程中所拥有的全部资源。

一个线程可以创建和撤销另一个线程
同一个进程中的多个线程之间可以并发执行

区别与联系:
·特征: 多线程的意义在于一个应用程序中,有多个执行部分可以同时执行(并发性),但操作系统并没有将多个线程看做是多个独立的应用,来实现进程的调度和管理以及资源的分配。

·执行:每个独立的线程有一个程序运行的入口,顺序执行序列和程序的出口。线程不能独立执行必须依存在应用程序中,由应用程序提供多个线程的执行控制

·不同的操作系统资源管理的方式:进程具有独立的地址空间,一个进程崩溃后,在保护模式下不会对其他进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉了就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但进程之间的切换,耗费资源较大,效率要差一些。但对要求同时进行又要共享某些变量的并发操作,只能用线程不能用进程。

·进程中有一个私有的虚拟的地址空间,只能被它所包含的线程访问

·每个进程中至少拥有一个线程

 

死锁:两个或多个线程之间相互等待对方结束而引起阻塞的情况
解决方案:
1.在同一时刻不允许一个线程访问多个资源
为资源的访问权的获取定义一个关系顺序。当一个线程获取r1的访问权后,将无法获取r2的访问权。访问权的释放要遵循相反的顺序

2.为所有访问资源的请求系统地定义一个最大等待时间(超时时间),并妥善处理请求失败的情况

线程操作