Java语言入门(九)——线程类及多线程
发布日期:2022-02-28 07:22:50 浏览次数:21 分类:技术文章

本文共 9518 字,大约阅读时间需要 31 分钟。

Java语言入门

线程与进程

1 进程是指运行中的应用程序,每一个进程都有自己独立的内存空间。对一个应用程序可以同时启动多个进程。

2 线程是指进程中的一个执行流程,有时也称为执行情景。一个进程可以由多个线程组成,即在一个进程中可以同时运行多个不同的线程,它们分别执行不同的任务。当进程内的多个线程同时运行,这种运行方式称为并发运行。
3 进程消失了,线程还存在么?答:不在
4 线程消失了,进程还会存在么?答:可能在
5 线程依附进程 比进程小,不同进程的线程不可比较大小
JVM 对于一个java系统,至少要启动两个线程main gc

java.lang.Thread	public static Thread currentThread()public final String getName()class Test{
public static void main(String args[]) {
System.out.println(Thread.currentThread().getName()); }}

线程的创建和启动方法

1 定义一个Thread类的子类,覆盖Thread类的run()方法,然后创建该子类的实例。

2 定义一个实现Runnable接口的类,实现它的run()方法,然后将这个类的实例作为Thread的构造方法的参数,创建Thread类的实例。
3 两种创建线程的方法是有区别的,对于共享资源来说,最好用实现runnable接口的方法

class TT extends Thread//线程的第一种创建方法{
public void run() {
for(int i=0;i<10;i++) System.out.println(Thread.currentThread().getName());}}class Test-9.1{
public static void main(String[] args) {
TT t1=new TT(); t1.run(); System.out.println(Thread.currentThread().getName()+";");}}//输出11个main
class TT extends Thread{
public void run() {
for(int i=0;i<10;i++) System.out.println(Thread.currentThread().getName()); }}class Test-9.2{
public static void main(String[] args) {
TT t1=new TT(); //t1.run(); t1.start();//线程的启动 System.out.println(Thread.currentThread().getName()+";");}}//输出main;和10个Thread-0
class TT extends Thread{
public void run() {
for(int i=0;i<10;i++) System.out.println(Thread.currentThread().getName()); }}class Test-9.3{
public static void main(String[] args) {
TT t1=new TT(); TT t2=new TT(); TT t3=new TT(); t1.setName("huang"); t1.start(); t2.start(); t3.start();System.out.println(Thread.currentThread().getName()+";");}}
class TT implements Runnable//线程的第二种创建方法{
public void run() {
for(int i=0;i<10;i++) System.out.println(Thread.currentThread().getName());}}class Test-9.4{
public static void main(String[] args) {
Runnable t=new TT(); Thread t1=new Thread(t); t1.start(); System.out.println(Thread.currentThread().getName()+";");}}//输出main;和10个Thread-0
class TT extends Thread//实现售票{
/*static*/ int tickets=20; public void run() {
//int tickets=20;错误 for (int i=0;i<40;i++) {
if (tickets>0) {
System.out.println(Thread.currentThread().getName()+";"+tickets--); }}} }class Test-9.5{
public static void main(String args[]) {
TT t1=new TT(); t1.setName("1"); TT t2=new TT(); t2.setName("2"); TT t3=new TT(); t3.setName("3"); t1.start(); t2.start(); t3.start(); System.out.println(Thread.currentThread().getName()+"*****");} }
class TT implements Runnable//实现售票{
/*static*/ int tickets=20; public void run() {
//int tickets=20;错误 for (int i=0;i<40;i++) {
if (tickets>0) {
System.out.println(Thread.currentThread().getName()+";"+tickets--); }}} }class Test-9.6{
public static void main(String args[]) {
TT t1=new TT(); /*TT t2=new TT();TT t3=new TT();*/ new Thread(t1,"1").start(); new Thread(t1,"2").start(); new Thread(t1,"3").start(); System.out.println(Thread.currentThread().getName()+"*****");} }
class TT implements Runnable{
static int tickets=20; public void run()/*throws Exception 错误*/ {
for(int i=0;i<40;i++) {
if(tickets>0) {
try {
Thread.sleep(500);}//只是让线程执行速度减缓,不影响代码执行本身 catch(Exception e){
} System.out.println(Thread.currentThread().getName()+":"+tickets--);}} }}class Test-9.7{
public static void main(String[] args) throws Exception {
TT t1=new TT(); TT t2=new TT(); TT t3=new TT(); new Thread(t1,"1站").start(); new Thread(t2,"2站").start(); new Thread(t3,"3站").start();}//出现错误有:重复、0、-1//线程的安全性问题(同步)

线程同步synchronized(同步代码块、同步方法)以及锁旗标

class TT implements Runnable{
static int tickets=20; String name="huang"; public void run() {
for(int i=0;i<40;i++) {
synchronized(name) //同步代码块 //synchronized(this) {
if(tickets>0) {
try {
Thread.sleep(500);}//只是让线程执行速度减缓,不影响代码执行本身 catch(Exception e){
} System.out.println(Thread.currentThread().getName()+":"+tickets--);}} }}class Test-9.8{
public static void main(String[] args) throws Exception {
TT t1=new TT(); TT t2=new TT(); TT t3=new TT(); new Thread(t1,"1站").start(); new Thread(t2,"2站").start(); new Thread(t3,"3站").start();} //synchronized(公认对象名[锁旗标])/*添加同步代码块对象,必须是公认的。不能在run方法里,若在run方法则无效*/

售票实例讲解

public class ProducerAndConsumer {
/** * 假定开始售票处并没有票,一个线程往里存票,另一个线程则往外卖票。 * 新建一个票类对象,让存票和售票线程都访问它。 * 两个线程共享同一个数据对象来实现对同一份数据的操作 */ public static void main(String[] args) {
Tickets t=new Tickets(10); //新建一个票类对象,总票数作为参数 new Producer(t).start(); //以票类对象为参数创建存票线程对象,并启动 new Consumer(t).start();//以同一个票类对象为参数创建售票线程,并启动 } } //票类 class Tickets{
int number=0; //票号 int size; //总票数 boolean available=false; //表示目前是否有票可售 public Tickets(int size){
this.size=size;}//构造函数,传入总票数参数 } //存票线程 class Producer extends Thread{
Tickets t=null; public Producer(Tickets t) {
this.t=t; }//构造函数:以一个票类为参数 public void run() {
while(t.number
size表示售票结束 } }

Thread类的方法

1 currentThread() 返回当前运行的Thread对象。

2 start() 启动一个线程。
3 run() 线程体,由start()方法调用,当run()方法返回时,当前的线程结束。
4 stop() 使调用它的线程立即停止执行。
5 sleep(int n)使线程睡眠n毫秒,n毫秒后,线程可以再次运行。
6 suspend() 使线程挂起,暂停运行。
7 resume() 恢复挂起的线程,使其处于可运行状态(Runnable)。
8 yield() 将CPU控制权主动移交到下一个可运行线程。
9 setPriority() 设置线程优先级。 getPriority() 返回线程优先级。
10 setName() 设置线程的名字。 getName() 返回该线程的名字。
11 isAlive( ) 如果线程已被启动并且未被终止,那么isAlive( )返回true。如果返回false,则该线程是新创建或是已被终止的。

死锁

1 死锁是程序运行时发生的一种状态

2 产生原因:多个线程共享同一资源时,要进行加锁操作(同步),但是,过多的同步会造成死锁
3 当一个线程等待由另一个线程持有的锁,而后者正在等待已被第一个线程持有的锁时,就会发生死锁。Java不监测也不试图避免这种情况。因而保证不发生死锁就成了程序员的责任

class ST implements Runnable      //死锁程序的模拟:{
int ticket=10; String str=new String("hh");/*添加同步代码块对象,必须是公认的。不能在run方法里,若在run方法则无效*/ public void run() {
if(str.equals("huang")) {
for (int i=0;i<30 ;i++ ) {
this.sale(); } else {
for (int i=0;i<30 ;i++ ) {
synchronized(str) //str称为锁旗标或监视器,有0,1状态,进去后为0,出来后为1 {
if (ticket>0) {
try{
Thread.sleep(100); } catch (Exception e){
} synchronized(this) {
} System.out.println(Thread.currentThread().getName()+" :"+ticket--);/*ticket>0和ticket--不是原子性操作时,解决方法:(1)代码写进同步代码,synchronized()速度慢,因为synchronized()每次检查状态*/}}} }}public synchronized void sale() //改为public void sale()不同步,同步方法的锁旗标为this //买票的方法,加上synchronized,该方法就同步{
if (ticket>0) {
try {
Thread.sleep(100);} catch (Exception e){
} synchronized(str){
} System.out.println("i am here"); System.out.println(Thread.currentThread().getName()+" :"+ticket--);}}}class Test-9.10{
public static void main(String[] args) {
ST s=new ST(); Thread t=new Thread(s,"station1"); Thread t1=new Thread(s,"station2"); t.start(); try{
Thread.sleep(100);} catch(Exception e){
} s .str="huang"; t1.start(); } }

对象数组

class Person             //对象数组{
String name; int age; int ID; public void say() {
System.out.println(name+";"+age); }}class Test-9.11{
public static void main(String[] args) {
Person[] p=new Person[10];//生成10个对象 //对象数组。每个单元存放的都是一个对象 Person s=new Person(); p[0]=s; p[0].name="zhangsan"; p[0].ID=1;p[0].say();}

在这里插入图片描述

内存图讲解

1 程序中用关键字new出来的东西都是存放在heap segment。

2 程序中的局部变量存放在stack segment,这些局部变量是在具体方法执行结束之后,系统自动释放内存资源(而heap segment中的资源需要java垃圾回收机制来处理)。形参一定在栈stack内存里
3 程序中的方法,是内存中的code segment中的,而且是多个对象 共享一个代码空间区域。
4 static静态变量,需要放在内存中的data segment

生产者与消费者实例讲解

//生产者与消费者问题//涉及线程的通信class SZP  //山楂片{
private int ID; public SZP(int ID) {
this.ID=ID;} public String toString() {
return "SZP"+ID;}}class RQ //容器{
int top=0; SZP [] sz = new SZP[10]; public synchronized void push(SZP s) {
if(top==sz.length) {
try{
this.wait(); } //wait时,锁给别人,才自动释放;sleep睡觉时,锁还在。 catch (Exception e){
} } this.notify(); //notify()唤醒,唤醒的是别人,不是自己 sz[top]=s; top++; } public synchronized SZP pop() {
if(top==0) {
try{
this.wait();} catch (Exception e){
} } this.notify(); top--; return sz[top]; }}class Producer implements Runnable //生产者{
RQ r=null; public Producer(RQ r) {
this.r=r;} public void run() {
for(int i=0;i<30;i++) {
SZP s=new SZP(i); r.push(s); try{
Thread.sleep(10);} catch (Exception e){
} System.out.println("produce: "+s); } }}class Consumer implements Runnable //消费者{
RQ r=null; public Consumer(RQ r) {
this.r=r;} public void run() {
for(int i=0;i<30;i++) {
SZP s=r.pop(); try{
Thread.sleep(1000);} catch (Exception e){
} System.out.println("consumer: "+s); } }}class Test-9.12{
public static void main(String [] args) {
RQ r=new RQ(); Producer p=new Producer(r); Consumer c=new Consumer(r); new Thread(p).start(); new Thread(c).start(); }}

转载地址:https://blog.csdn.net/weixin_45854582/article/details/106151329 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Java语言入门(十)——容器
下一篇:Java语言入门(十一)——流

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月02日 20时18分07秒