文档库 最新最全的文档下载
当前位置:文档库 › java例子——Java多线程机制

java例子——Java多线程机制

6.1 Java多线程机制

6.1.1基本概念

线程控制方法

public class Thread implements Runnable

{

public final static int MIN_PRIORITY;

public final static int NORM_PRIORITY;

public final static int MAX_PRIORITY;

public Thread();

public Thread(Runnable target);

public Thread(ThreadGroup group, Runnable target);

public Thread(String name);

public Thread(ThreadGroup group, String name);

public Thread(Runnable target, String name);

public Thread(ThreadGroup group, Runnable target, String name);

public void run();

public synchronized native void start();

public final void stop();

public final synchronized void stop(Throwable o);

public static native void yield();

public static native void sleep(long millis) throws InterruptedException;

public static void sleep(long millis, int nanos) throws InterruptedException public final void suspend();

public final void resume();

public final synchronized void join(long millis) throws InterruptedException; public final synchronized void join(long millis, int nanos)throws InterruptedException;

public final void join() throws InterruptedException;

public void interrupt();

public static boolean interrupted();

public boolean isInterrupted();

public void destroy();

public final native boolean isAlive();

public final void setPriority(int newPriority);

public final int getPriority();

public final void setName(String name);

public final String getName();

public final ThreadGroup getThreadGroup();

public static native Thread currentThread();

public static int activeCount();

public static int enumerate(Thread tarray[]);

public native int countStackFrames();

public static void dumpStack();

public final void setDaemon(boolean on);

public final boolean isDaemon();

public void checkAccess();

public String toString();

}

____________________________________________________________

6.1.2多线程实现方法

例1:下面程序演示如何用生成Thread子类的方法来创建新线程。

//ThreadTest1.java

public class ThreadTest1

{

ThreadTest1()

{

FirstThread first = new FirstThread();

SecondThread second = new SecondThread();

first.start();

second.start();

}

public static void main(String[] args)

{

new ThreadTest1();

}

}

class FirstThread extends Thread

{

public void run()

{

try

{

System.out.println("First thread starts running."); for(int i=0; i<10; i++)

{

System.out.println("First " + i);

sleep(1000);

}

System.out.println("First thread finishes running.");

catch (InterruptedException e) {}

}

}

class SecondThread extends Thread

{

public void run()

{

try

{

System.out.println("\tSecond thread starts running.");

for(int i=0; i<10; i++)

{

System.out.println("\tSecond " + i);

sleep(1000);

}

System.out.println("\tSecond thread finishes running.");

}

catch (InterruptedException e) {}

}

}

程序设计了两个线程FirstThread类和SecondThread类,它们都是Thread类的子类覆盖了run()方法,在其中分别进行打印数值的工作。

除了这两个线程外,还有一个线程在执行,就是启动类线程,称它为主线程,它负责生成另外两个线程,再用start()方法启动这两个线程。

线程first和second启动后,并发执行。观察执行结果会发现两个线程交替打印数据,而不是一个线程完成了所有打印工作后,另一个线程才开始打印工作,这就是多线程的本质。提示:线程在调用Thread类方法sleep()睡眠时,有可能产生异常,要求应用程序用try-catch捕获这个异常,如果不用try-catch,程序将出错。

某次的运行结果:

First thread finishes running.

First 0

Second thread starts running.

Second 0

Second 1

First 1

First 2

Second 2

First 3

Second 3

First 4

Second 5

First 5

First 6

Second 6

First 7

Second 7

First 8

Second 8

First 9

Second 9

First thread finishes running.

Second thread finishes

________________________________________________

例2:下面程序演示如何用生成Thread子类的方法来创建新线程。

//ThreadTest2.java

public class ThreadTest2

{

ThreadTest2()

{

FirstThread first = new FirstThread();

SecondThread second = new SecondThread();

first.start();

second.start();

try

{

first.join();

System.out.println("Waiting for first thread to finish..."); System.out.println("Waking up second thread...");

second.resume();

}

catch (InterruptedException e) {}

}

public static void main(String[] args)

{

new ThreadTest2();

}

}

class FirstThread extends Thread

{

public void run()

{

try

{

System.out.println("First thread STARTS running.");

for(int i=0; i<10; i++)

{

System.out.println("First " + i);

sleep(1000);

}

System.out.println("First thread FINISHES running.");

}

catch (InterruptedException e) {}

}

}

class SecondThread extends Thread

{

public void run()

{

try

{

System.out.println("\tSecond thread STARTS running.");

for(int i=0; i<10; i++)

{

if(i== 4)

suspend();

System.out.println("\tSecond " + i);

sleep(1000);

}

System.out.println("\tSecond thread FINISHES running.");

}

catch (InterruptedException e) {}

}

}

程序仍然使用两个线程打印数据,不同的是second线程在打印数据过程中,发现是数值4,则调用suspend()方法,暂停本身的执行。

主线程用join()方法等线程first执行结束后,用resume()方法来唤醒second线程,second 线程被唤醒后,将继续完成打印工作。

提示:join()也将出现InterruptedException异常,所以必须捕获异常。

某次的运行结果:

First thread STARTS running.

First 0

Second thread STARTS running.

Second 0

First 1

Second 1

First 2

Second 2

First 3

Second 3

First 4

First 5

First 6

First 7

First 8

First 9

First thread FINISHES running.

Waiting for first thread to finish...

Waking up second thread...

Second 4

Second 5

Second 6

Second 7

Second 8

Second 9

Second FINISHES finishes

____________________________________________________________ 例3:下面的程序说明如何用接口来创建线程。

//RunTest.java

public class RunTest

{

RunTest()

{

FirstThread first = new FirstThread();

SecondThread second = new SecondThread();

Thread thread1 = new Thread(first);

Thread thread2 = new Thread(second);

thread1.start();

thread2.start();

}

public static void main(String[] args)

{

new RunTest();

}

}

class FirstThread implements Runnable

{

public void run()

{

try

{

System.out.println("First thread starts running.");

for(int i=0; i<10; i++)

{

System.out.println("First " + i);

Thread.sleep(1000);

}

System.out.println("First thread finishes running.");

}

catch (InterruptedException e) {}

}

}

class SecondThread implements Runnable

{

public void run()

{

try

{

System.out.println("\tSecond thread starts running.");

for(int i=0; i<10; i++)

{

System.out.println("\tSecond " + i);

Thread.sleep(1000);

}

System.out.println("\tSecond thread finishes running.");

}

catch (InterruptedException e) {}

}

}

这个程序与ThreadTest1.java有相同的功能,只不过现在用实现Runnable接口的方法来创建和执行线程。

______________________________________________

_____________________________________________

6.2 输入输出流类

6.2.1文件系统

1.文件路径和属性

例子:下面的程序首先判断给定文件是否存在,如果存在则显示文件路径、绝对路径等,然后再查询文件的属性。

//FileTest1.java

import java.io.*;

class FileTest1

{

public static void main(String[] args)

{

String path;

if(args.length != 1)

{

System.err.println("Usage: java FileTest1 File or Dir");

System.exit(-1);

}

File f = new File(args[0]);

if (f.exists())

{

System.out.println("----------------------------- ");

System.out.println("Absolute Path: " + f.getAbsolutePath());

System.out.println("File Path: " + f.getPath());

System.out.println("File Name: " + f.getName());

System.out.println("Parent Dirtory: " + f.getParent());

System.out.println("----------------------------- ");

String canRead = f.canRead() ? "Yes" : "No";

String canWrite = f.canWrite() ? "Yes" : "No";

String isFile = f.isFile() ? "Yes" : "No";

String isDir = f.isDirectory() ? "Yes" : "No";

String isAbs = f.isAbsolute() ? "Yes" : "No";

System.out.println("Readable: "+canRead);

System.out.println("Writable: "+canWrite);

System.out.println("Is directoty: "+isDir);

System.out.println("Is file: "+isFile);

System.out.println("Is absolute path: "+isAbs);

}

else System.out.println("Cannot found file: " + args[0]);

}

}

这是一个Application程序,用命令行参数接受输入文件名。读者可以用不同的命令行参数来执行上面的程序,体会上述方法的区别。

运行:java FileTest1 d:\java\filetest1

运行结果:

-----------------------------

Absolute Path: d:\java\filetest1

File Path: d:\java\filetest1

File Name: filetest1

Parent Dirtory: d:\java

-----------------------------

Readable: Yes

Writable: Yes

Is directoty: Yes

Is file: No

Is absolute path:Yes

—————

运行:java FileTest1 \java\filetest1

运行结果:

-----------------------------

Absolute Path: d:\java\filetest1

File Path: \java\filetest1

File Name: filetest1

Parent Dirtory: \java

-----------------------------

Readable: Yes

Writable: Yes

Is directoty: Yes

Is file: No

Is absolute path:No

—————

运行: java FileTest1 \java\filetest1\filetest1.java

运行结果:

-----------------------------

Absolute Path: d:\java\filetest1\filetest1.java

File Path: \java\filetest1\filetest1.java

File Name: filetest1.java

Parent Dirtory: \java\filetest1

-----------------------------

Readable: Yes

Writable: Yes

Is directoty: No

Is file: Yes

Is absolute path:No

—————

运行:java FileTest1 \java

运行结果:

-----------------------------

Absolute Path: d:\java

File Path: \java

File Name: java

Parent Dirtory: \

-----------------------------

Readable: Yes

Writable: Yes

Is directoty: Yes

Is file: No

Is absolute path:No

—————

运行:java FileTest1 \java

运行结果:

-----------------------------

Absolute Path: d:\

File Path: \

File Name:

Parent Dirtory: null

-----------------------------

Readable: Yes

Writable: Yes

Is directoty: Yes

Is file: No

Is absolute path:No

————————————————————————————————————————————————————————

2.创建目录和删除文件

例2:

//FileTest2.java

import java.io.*;

class FileTest2

{

public static void main(String[] args)

{

File dir, subdir;

if(args.length != 1)

{

System.err.println("Usage: java FileTest2 ");

System.exit(-1);

}

dir = new File(args[0]);

if(dir.exists())

System.out.println(dir.getPath() + " already exist!");

else

{

if(dir.mkdirs()) //说明区别

{

System.out.println("Created directory: " + dir.getAbsolutePath());

subdir = new File(dir, "newSub");

if (subdir.mkdir())

{

System.out.println("Created subdirectory: " + subdir.getAbsolutePath());

subdir.delete(); //删除才创建的目录

}

else

System.out.println("Could not create subdirectory " + subdir.getAbsolutePath());

dir.delete();

}

else

System.out.println("Could not create directory " + dir.getAbsolutePath());

}

}

}

————————————————————————————

————————————————————————————

3.文件更名

//FileRename.java

import java.io.*;

class FileRename

{

public static void main(String[] args)

{

String message;

if (args.length != 2)

{

System.err.println("Usage: java FileRename ");

System.exit(-1);

}

File f1 = new File(args[0]);

File f2 = new File(args[1]);

if (f1.equals(f2))

{

System.err.println("Cannot rename a file to itself");

System.exit(-1);

}

message = f1.renameTo(f2) ? " renamed to " : " could not be renamed to "; System.out.println(f1.getPath() + message + f2.getPath());

}

}

————————————————————————————————————————————————

4.目录清单

//FileDir.java

import java.io.File;

import java.util.Date;

class FileDir

{

public static void main(String[] args)

{

if (args.length != 1)

{

System.err.println("Usage: java FileDir filepath");

System.exit(-1);

}

File f = new File(args[0]);

String[] ls = f.list();

for (int i = 0; ls != null && i

printOne(new File(f, ls[i]));

}

public static void printOne(File f)

{

if (f.exists())

{

System.out.print(f.canRead() ? "r" : "-");

System.out.print(f.canWrite() ? "w" : "-");

System.out.print(f.isDirectory() ? "d" : "-");

if(!f.isDirectory())

System.out.print("\t\t" + f.length());

else

System.out.print("\t

\t");

System.out.print('\t');

System.out.print(new Date(https://www.wendangku.net/doc/2f17674335.html,stModified()));

System.out.print('\t');

}

else

{

System.out.print("\t\t\t\t\t");

}

System.out.println(f.getName());

}

}

运行:java FileDir \java\filetestc

运行结果:

rw- 1130 Tue Oct 26 16:30:23 CST 2001 FileTest.java rw- 1492 Tue Oct 26 16:30:30 CST 2001 FileTest.class

运行:java FileDir \java\

运行结果:

rwd

Tue Oct 26 16:34:33 CST 2001 Computer

rw- 1203 Tue Oct 26 16:30:23 CST 2001 Hello.java rw- 1345 Tue Oct 26 16:30:30 CST 2001 Hello.class rwd

Tue Oct 26 16:30:23 CST 2001 UsePhoneCard rwd Tue Oct 26 16:30:23 CST 2001 MultiPara

——————————————————————————————

——————————————————————————————

6.2.2读写文件

RandomAccessFile类,它的定义如下:

public class RandomAccessFile implements DataOutput, DataInput

{

public RandomAccessFile(String name, String mode) throws IOException;

public RandomAccessFile(File file, String mode) throws IOException;

//misc methods

public final FileDescriptor getFD() throws IOException;

public long getFilePointer() throws IOException;

public void seek(long pos) throws IOException;

public long length() throws IOException;

public void close() throws IOException;

public int read() throws IOException;

public int read(byte b[], int off, int len) throws IOException;

public int read(byte b[]) throws IOException;

//DataInput interface

public final void readFully(byte b[]) throws IOException;

public final void readFully(byte b[], int off, int len) throws IOException; public int skipBytes(int n) throws IOException;

public final boolean readBoolean() throws IOException;

public final byte readByte() throws IOException;

public final int readUnsignedByte() throws IOException;

public final short readShort() throws IOException;

public final int readUnsignedShort() throws IOException;

public final char readChar() throws IOException;

public final int readInt() throws IOException;

public final long readLong() throws IOException;

public final float readFloat() throws IOException;

public final double readDouble() throws IOException;

public final String readLine() throws IOException;

public final String readUTF() throws IOException;

//DataOutput interface

public void write(int b) throws IOException;

public void write(byte b[]) throws IOException;

public void write(byte b[], int off, int len) throws IOException;

public final void writeBoolean(boolean v) throws IOException;

public final void writeByte(int v) throws IOException;

public final void writeShort(int v) throws IOException;

public final void writeChar(int v) throws IOException;

public final void writeInt(int v) throws IOException;

public final void writeLong(long v) throws IOException;

public final void writeFloat(float v) throws IOException;

public final void writeDouble(double v) throws IOException;

public final void writeBytes(String s) throws IOException;

public final void writeChars(String s) throws IOException;

public final void writeUTF(String str) throws IOException;

}

————————————————————————————

例1:下面的程序说明向文件中写出数据的方法

//RandomTest.java

import java.io.*;

class RandomTest

{

public static void main(String[] args)

{

RandomAccessFile raf = null;

if (args.length != 1)

{

System.err.println("Usage: java RandomTest "); System.exit(-1);

}

try

{

raf = new RandomAccessFile(args[0], "rw");

char a = 'a';

byte b = 2;

String c = "abc";

byte[] b2 = {'a', 'b', 'c'};

raf.write(b); //02

raf.write(b2, 0, b2.length);//61 62 63

raf.writeBoolean(true);//01

raf.writeChar(a);//00 61

raf.writeBytes(c);//61 62 63

raf.writeChars(c);//00 61 00 62 00 63

raf.writeUTF(c);//00 03 61 62 63

raf.writeUTF("abc\n");//00 04 61 62 63 0a

System.out.println("Length of file: " + raf.length());

}

catch (IOException e)

{

System.err.println(e);

}

finally

{

try

{

raf.close();

}

catch (Exception e)

{

System.err.println(e);

}

}

}

}

运行程序:

java RandomTest output

结果:

Length of file: 27

output文件包含的内容用十六进制表示为:

02 61 62 63 01 00 61 61 62 63 00 61 00 62 00 63 00 03 61 62 63 00 04 61 62 63 0a ————————————————————————————

例2:下面的程序把一个文件复制成另一个文件。

//RandCopy.java

import java.io.*;

class RandCopy

{

public static void main(String args[])

{

RandomAccessFile raf1 = null, raf2 = null;

long fileSize = -1;

byte[] buffer;

if(args.length != 2)

{

System.out.println("Usage: java RandCopy ");

System.exit(0);

}

if(args[0].equals(args[1]))

{

System.out.println(args[0]);

System.out.println("File cannot copied onto itself!");

System.exit(-1);

}

try

{

raf1 = new RandomAccessFile(new File(args[0]), "r");

//其中raf1表示原文件,以只读方式打开,

fileSize = raf1.length();//获得原文件的长度

}

catch (IOException e)

{

System.out.println("Cannot find " + args[0]);

System.exit(-1);

}

try

{

raf2 = new RandomAccessFile(new File(args[1]), "rw");

// raf2表示新复制文件,以读写方式打开

}

catch (IOException e)

{

System.out.println("Cannot open " + args[1]);

System.exit(-1);

}

buffer = new byte[(int)fileSize];

try

{

raf1.readFully(buffer, 0, (int) fileSize);

//一次把所有数据读入内存

raf2.write(buffer, 0, (int) fileSize);

//全部写出到新文件中

}

catch(IOException e)

{

System.out.println("Cannot copy file " + args[0] + "to " + args[1]); }

finally

{

try

{

raf1.close();

raf2.close();

}

catch(Exception e)

{

System.err.println(e);

}

}

}

}

————————————————————————————————————————————————————————————

6.2.3抽象流类

1.InputStream类

InputStream类的定义如下:

public abstract class InputStream extends Object

{

public InputStream();

public abstract int read() throws IOException;

public int read(byte b[]) throws IOException ;

public int read(byte b[], int off, int len) throws IOException ;

public long skip(long n) throws IOException ;

public int available() throws IOException ;

public void close() throws IOException ;

public synchronized void mark(int readlimit) ;

public synchronized void reset() throws IOException ;

public boolean markSupported() ;

}

——————————————————————————

2.OutputStream类

与输入流类相对应的另一个抽象类是OutputStream类,它定义了与输出操作有关的方法,其定义如下:

public abstract class OutputStream extends Object

{

public OutputStream();

public abstract void write(int b) throws IOException;

public void write(byte b[]) throws IOException;

public void write(byte b[], int off, int len) throws IOException;

public void flush() throws IOException;

public void close() throws IOException;

}

————————————————————————————————————————————————————————

6.2.4文件输入输出流类

1.FileInputStream类

FileInputStream类提供从文件中读入数据的方法,其定义为:

public class FileInputStream extends InputStream

{

public FileInputStream(String name) throws FileNotFoundException;

public FileInputStream(File file) throws FileNotFoundException;

public FileInputStream(FileDescriptor fdObj);

public int read() throws IOException;

public int read(byte b[]) throws IOException;

public int read(byte b[], int off, int len) throws IOException;

public long skip(long n) throws IOException;

// 使文件的读入指针向前或向后移动n个字节,其参数值相对于当前文件指针

public int available() throws IOException;

//返回文件输入流中可供读入的字节数,实际上就是文件的长度。

public void close() throws IOException;

public final FileDescriptor getFD() throws IOException;

protected void finalize() throws IOException;

}

————————————————————————————————

例子:下面的程序说明FileInputStream类的使用方法。程序实现类似MS-DOS操作系统中type命令,用于显示文件内容。

//FileType.java

import java.io.*;

class FileType

{

public static void main(String[] args)

{

if (args.length != 1)

{

System.err.println("Usage: java FileType ");

System.exit(-1);

}

File file = new File(args[0]);

try

{

FileInputStream in = new FileInputStream(file);

int c;

int i = 0;

while ((c = in.read()) > -1)

{

if((char)c == '\n') i++; //统计行数

System.out.print((char)c);

}

in.close();

System.out.flush();

System.out.println("\n\n\n----------------");

System.out.println("File " + args[0] + " Lines: " + i);

}

catch (FileNotFoundException e)

{

System.err.println(file + " is not found");

}

catch (IOException e)

{

e.printStackTrace();

}

}

}

程序在生成FileInputStream对象时,用File对象给出文件名,虽然比用字符串给出文件名稍麻烦点,

但这种方法使应用程序独立于平台,是一种良好的设计习惯。

程序在显示文件内容时使用了System.out.print()方法,而不是以前程序中常用的方法System.out.println()。

两者的区别是:println()执行时,立即把字符显示在屏幕上,并且每次调用println()方法,它总是在新的一行输出数据。

print()执行时,并不立即显示数据,而把数据缓存在输出流中,直到遇到新行字符'\n'或执行了flush()方法后,才使字符显示在屏幕上。

如果程序中使用println(),那么在屏幕上的显示情况就是一行一个字符,不是原来文件的行格式。

————————————————————————————————

Java多线程和输入输出流

班级:13科技2班学号:201324131225 姓名:许耿宁 Java多线程和输入输出流 一、实验目的: 1.熟悉利用Thread类建立多线程方法。 2.熟悉利用Thread接口建立多线程方法。 3.熟悉Java的文件读写机制,练习输入输出流的使用。 二、实验内容: 1.阅读下列程序,分析并上机检验其功能。 public class DelayRunnable implements Runnable{ private static int count=0; private int no; private int delay; public DelayRunnable(){ count++; no=count; } public void run(){ try{ for (int i=0;i<10;i++){ delay=(int)(Math.random()*5000); Thread.sleep(delay); System.out.println("Thread "+no+" with a delay "+delay); } }catch(InterruptedException e){} } } class MyRunnable{ public static void main(String args[]){ DelayRunnable r1 = new DelayRunnable();

DelayRunnable r2 = new DelayRunnable(); Thread thread1=new Thread(r1); Thread thread2=new Thread(r2); thread1.start(); thread2.start(); try{ Thread.sleep(1000); }catch(InterruptedException e){ System.out.println("Thread wrong"); } } } 2.将上列程序利用Runnable接口改写,并上机检验。 3.创建简单的程序ThreeThread.java,该程序将创建三个线程,每个线程应当显示它所运行的时间(可以考虑使用Date类或Calendar类)。 4.键盘输入10个整数,从小到大进行排序。 5.接收键盘输入的字符串,用FileInputStream类将字符串写入文件,用 FileOutputStream类读出文件内容显示在屏幕上。 6.将一个文本文件的内容按行读出,每读出一行就顺序加上行号,并写入到另一个文件中。 三、实验要求: 1.通过实验掌握Thread 、Runnable使用方法; 2.程序必须能够实现多线程; 3.程序必须能够完成题目要求; 4.通过实验掌握文件输入输出流的使用方法; 5.程序必须能够从键盘接收字符串并保存在文件中; 6.程序必须能够读出文件内容显示在屏幕上; 7.写出实验报告。 四、实验代码及截图: 第一题: 在编译器上运行程序得到截图所示结果:

Java第七单元练习题-Java多线程机制

7Java多线程机制 7.1单项选择题 1. 线程调用了sleep()方法后,该线程将进入()状态。 A. 可运行状态 B. 运行状态 C. 阻塞状态 D. 终止状态 2. 关于java线程,下面说法错误的是() A. 线程是以CPU为主体的行为 B. java利用线程使整个系统成为异步 C. 创建线程的方法有两种:实现Runnable接口和继承Thread类 D. 新线程一旦被创建,它将自动开始运行 3. 在java中的线程模型包含() A. 一个虚拟处理器 B. CPU执行的代码 C. 代码操作的数据 D. 以上都是 4.在java语言中,临界区可以是一个语句块,或者是一个方法,并用()关键字标识。 A. synchronized B. include C. import D. Thread 5. 线程控制方法中,yield()的作用是() A. 返回当前线程的引用 B. 使比其低的优先级线程执行 C. 强行终止线程 D. 只让给同优先级线程运行 6. 线程同步中,对象的锁在()情况下持有线程返回 A. 当synchronized()语句块执行完后 B. 当在synchronized()语句块执行中出现例外(exception)时 C. 当持有锁的线程调用该对象的wait()方法时 D. 以上都是 7. 在以下()情况下,线程就进入可运行状态 A. 线程调用了sleep()方法时 B. 线程调用了join()方法时

C. 线程调用了yield()方法时 D. 以上都是 8. java用()机制实现了进程之间的异步执行 A. 监视器 B. 虚拟机 C. 多个CPU D. 异步调用 类的方法中,toString()方法的作用是() A. 只返回线程的名称 B. 返回当前线程所属的线程组的名称 C. 返回当前线程对象 D. 返回线程的名称 语言具有许多优点和特点,下列选项中,哪个反映了Java程序并行机制的特点() A. 安全性 B. 多线程 C. 跨平台 D. 可移值 11.以下哪个关键字可以用来对对象加互斥锁?() A. transient B. synchronized C. serialize D. static 12.下面关于进程、线程的说法不正确的是( )。 A.进程是程序的一次动态执行过程。一个进程在其执行过程中,可以产生多个线程——多线程,形成多条执行线索。 B.线程是比进程更小的执行单位,是在一个进程中独立的控制流,即程序内部的控制流。线程本身不能自动运行,栖身于某个进程之中,由进程启动执行。 C.Java多线程的运行与平台无关。 D.对于单处理器系统,多个线程分时间片获取CPU或其他系统资源来运行。对于多处理器系统,线程可以分配到多个处理器中,从而真正的并发执行多任务。 7.2填空题 1.________是java程序的并发机制,它能同步共享数据、处理不同的事件。 2.线程是程序中的一个执行流,一个执行流是由CPU运行程序的代码、__________所形 成的,因此,线程被认为是以CPU为主体的行为。 3.线程的终止一般可以通过两种方法实现:自然撤销或者是__________. 4.线程模型在java中是由__________类进行定义和描述的。 5.线程的创建有两种方法:实现_________接口和继承Thread类。 6.多线程程序设计的含义是可以将程序任务分成几个________的子任务。 7.按照线程的模型,一个具体的线程也是由虚拟的CPU、代码与数据组成,其中代码与数 据构成了___________,线程的行为由它决定。 8.ava中,新建的线程调用start()方法、如(),将使线程的状态从New(新建状态)转换为 _________。 9.多线程是java程序的________机制,它能同步共享数据,处理不同事件。 10.进程是由代码、数据、内核状态和一组寄存器组成,而线程是表示程序运行状态的

java多线程面试题

java多线程面试题 1.什么是多线程编程?什么时候使用? 多线程一般用于当一个程序需要同时做一个以上的任务。多线程通常用于GUI交互程序。一个新的线程被创建做一些耗时的工作,当主线程保持界面与用户的交互。 2.为什么wait(),notify()和notifyall()函数定义在Object类里面? 因为所有类都是继承于Object类,这样所有类就可以简单的进行多线程编程了。 3.wait()方法和sleep()方法有什么不同? sleep()方法执行后仍然拥有线程,只是延时。而wait方法放弃了线程控制,其它线程可以运行,想要再次运行是要重新开始。 4.Thread和Runnable有什么不同? JA V A线程控制着程序执行的主路径。当你用java命令调用JVM时,JVM创建了一个隐式线程来执行main方法。Thread类提供了主线程调用其它线程并行运行的机制。 Runnable接口定义了一个能被Thread运行的类。实现Runnable的类只需要实行run方法。可以很灵活的扩展现在的已经继承自其它父类的类。而thread则不可以,因为java 只允许继承一个父类。 Runnable可以共享数据,Thread是一个类,而Runnable是一个接口 5.我可以重载start()方法么? 可以重载,重载后还要重载run()方法, 9.编译运行下面的代码会发生什么? 1.public class Bground extends Thread{ 2.public static void main(String argv[]) 3.{ 4. Bground b = new Bground(); 5. b.run(); 6.} 7.public void start()

Java_2实用教程第4版_第12章_Java多线程机制

2014/1/20 第 1 页 注意:开始用功了! 1 2014/1/20 第 2 页 《Java2实用教程(第4版)》第12章 配合例子源代码一起使用 Power point 制作:耿祥义张跃平 Java多线程机制 2 2014/1/20 第 3 页 导读 主要内容 Java中的线程 Thread类与线程的创建 线程的常用方法 线程同步 协调同步的线程 线程联合 GUI线程 计时器线程 3 2014/1/20 第 4 页 §12.1 进程与线程 §12.1.1 操作系统与进程 程序是一段静态的代码,它是应用软件执行的蓝本。 进程是程序的一次动态执行过程,它对应了从代码加载、执行至执行完毕的一个完整过程,这个过程也是进程本身从产生、发展至消亡的过程。 现代操作系统可以同时管理一个计算机系统中的多个进程,即可以让计算机系统中的多个进程轮流使用CPU资源。 4 2014/1/20 第 5 页 §12.1.2 进程与线程 线程是比进程更小的执行单位,一个进程在其执行过程中,可以产生多个线程,形成多条执行线索,每条线索,即每个线程也有它自身的产生、存在和消亡的过程。 线程间可以共享进程中的某些内存单元(包括代码与数据),线程的中断与恢复可以更加节省系统的开销。 5 2014/1/20 第 6 页

§12.2 Java中的线程 §12.2.1 Java的多线程机制 Java语言的一大特性点就是内置对多线程的支持。 Java虚拟机快速地把控制从一个线程切换到另一个线程。这些线程将被轮流执行,使得每个线程都有机会使用CPU资源。 6 2014/1/20 第7 页 §12.2.2 主线程(main线程) 每个Java应用程序都有一个缺省的主线程。 当JVM(Java Virtual Machine 虚拟机)加载代码,发现main方法之后,就会启动一个线程,这个线程称为“主线程”(main线程),该线程负责执行main方法。 JVM一直要等到Java应用程序中的所有线程都结束之后,才结束Java应用程序。 7 2014/1/20 第8 页 §12.2.3 线程的状态与生命周期 建的线程在它的一个完整的生命周期中通常要经历如下的四种状态: 1.新建: 当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态。2.运行:线程必须调用start()方法(从父类继承的方法)通知JVM,这样JVM就会知道又有一个新一个线程排队等候切换了。一旦轮到它来享用CPU资源时,此线程的就可以脱离创建它的主线程独立开始自己的生命周期了。 3.中断:有4种原因的中断: ◆JVM将CPU资源从当前线程切换给其他线程,使本线程让出CPU的使用权处于中断状态。 ◆线程使用CPU资源期间,执行了sleep(int millsecond)方法,使当前线程进入休眠状。 ◆线程使用CPU资源期间,执行了wait()方法。 ◆线程使用CPU资源期间,执行某个操作进入阻塞状态。 4.死亡:处于死亡状态的线程不具有继续运行的能力。线程释放了实体。 8 2014/1/20 第9 页 例子1(Example12_1.java )通过分析运行结果阐述线程的4种状态。例子1在主线程中用Thread的子类创建了两个线程(SpeakElephant.java , SpeakCar.java ),这两个线程分别在命令行窗口输出20句“大象”和“轿车”;主线程在命令行窗口输出15句“主人”。 例子1的运行效果如图12.4。 例子1在不同的计算机运行或在同一台计算机反复运行的结果不尽相同,输出结果依赖当前CPU资源的使用情况。 9 2014/1/20 第10 页 §12.2.4 线程调度与优先级 处于就绪状态的线程首先进入就绪队列排队等候CPU资源,同一时刻在就绪队列中的线程可能有多个。Java虚拟机(JVM)中的线程调度器负责管理线程,调度器把线程的优先

JAVA 面试题总览(书签完整版)

JAVA面试题总览 JAVA基础 1.JAVA中的几种基本数据类型是什么,各自占用多少字节。 2.String类能被继承吗,为什么。 3.String,Stringbuffer,StringBuilder的区别。 4.ArrayList和LinkedList有什么区别。 5.讲讲类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数, 字段,当new的时候,他们的执行顺序。 6.用过哪些Map类,都有什么区别,HashMap是线程安全的吗,并发下使用的Map是什么, 他们内部原理分别是什么,比如存储方式,hashcode,扩容,默认容量等。 7.JAVA8的ConcurrentHashMap为什么放弃了分段锁,有什么问题吗,如果你来设计, 你如何设计。 8.有没有有顺序的Map实现类,如果有,他们是怎么保证有序的。 9.抽象类和接口的区别,类可以继承多个类么,接口可以继承多个接口么,类可以实现多个接 口么。 10.继承和聚合的区别在哪。 11.IO模型有哪些,讲讲你理解的nio,他和bio,aio的区别是啥,谈谈reactor模型。 12.反射的原理,反射创建类实例的三种方式是什么。 13.反射中,Class.forName和ClassLoader区别。 14.描述动态代理的几种实现方式,分别说出相应的优缺点。 15.动态代理与cglib实现的区别。 16.为什么CGlib方式可以对接口实现代理。 17.final的用途。 18.写出三种单例模式实现。 19.如何在父类中为子类自动完成所有的hashcode和equals实现?这么做有何优劣。 20.请结合OO设计理念,谈谈访问修饰符public、private、protected、default在应 用设计中的作用。 21.深拷贝和浅拷贝区别。 22.数组和链表数据结构描述,各自的时间复杂度。 23.error和exception的区别,CheckedException,RuntimeException的区别。 24.请列出5个运行时异常。 25.在自己的代码中,如果创建一个https://www.wendangku.net/doc/2f17674335.html,ng.String类,这个类是否可以被类加载器加 载?为什么。

JAVA线程程序设计(小时钟)实验报告(附完整代码)

线程程序设计 一、课题内容和要求 内容:设计和编写一个编写一个指针式时钟程序,应用线程实现时钟的走动。 要求:本实验旨在通过实验,培养学生将JAVA 线程的相关知识点(包括线程调度,线程同步等)有机结合并加以综合应用,在实验中设计多线程程序的能力。 二、设计思路分析 class Clock:一个指针式时钟的主类 class Layout: 添加窗口和时钟组件 class ClockPaint:定义时钟组件 三、概要设计 public class Clock extends JFrame { public static void main(String[] s) ; } class Layout extends JFrame { public Layout(); } class ClockPaint extends JPanel implements Runnable { int x, y, r; int h, m, s; double rad = Math.PI / 180; public ClockPaint(int x, int y, int r); public void paint(Graphics g); public void run(); } 时钟的绘制:

运行时钟: 四、详细设计 import java.awt.*; import javax.swing.*; import java.util.*; public class Clock extends JFrame { public static void main(String[] s) { new Layout(); } } class Layout extends JFrame {// 添加窗口和时钟组件public Layout() { ClockPaint cp = new ClockPaint(20, 20, 70); add(cp);

多线程常见面试题

1)现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完 后执行? T1.start(); T1.join(); T2.start(); T2.join(); T3.start() 2)11) 为什么我们调用start()方法时会执行run()方法,为什么我们不能直接调用run() 方法? start()方法最本质的功能是从CPU中申请另一个线程空间来执行run()方法中的代码,它和当前的线程是两条线,在相对独立的线程空间运行 ,也就是说,如果你直接调用线程对象的run()方法,当然也会执行,但那是在当前线程中执行,run()方法执行完成后继续执行下面的代码.而调用start()方法后,run()方法的代码会和当前线程并发(单CPU)或并行(多CPU)执行。 调用线程对象的run方法不会产生一个新的线程 3)在java中wait和sleep方法的不同? sleep()睡眠时,保持对象锁,仍然占有该锁; 而wait()睡眠时,释放对象锁。 sleep()使当前线程进入停滞状态(阻塞当前线程),让出CUP的使用、目的是不让当前线程独自霸占该进程所获的CPU资源,以留一定时间给其他线程执行的机会; sleep()是Thread类的Static(静态)的方法;因此他不能改变对象的机锁,所以当在一个Synchronized块中调用Sleep()方法是,线程虽然休眠了,但是对象的机锁并木有被释放,其他线程无法访问这个对象(即使睡着也持有对象锁)。 在sleep()休眠时间期满后,该线程不一定会立即执行,这是因为其它线程可能正在运行而且没有被调度为放弃执行,除非此线程具有更高的优先级。 wait()方法是Object类里的方法;当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,同时失去(释放)了对象的机锁(暂时失去机锁,wait(long timeout)超时时间到后还需要返还对象锁);其他线程可以访问; wait()使用notify或者notifyAlll或者指定睡眠时间来唤醒当前等待池中的线程。 wiat()必须放在synchronized block中,否则会在program runtime时扔出”https://www.wendangku.net/doc/2f17674335.html,ng.IllegalMonitorStateException“异常。 4)为什么wait, notify 和notifyAll这些方法不在thread类里面? 因为这些是关于锁的 而锁是针对对象的 锁用于线程的同步应用 决定当前对象的锁的方法就应该在对象中吧 我是这么理解的希望对你有帮助

Java第七单元练习题Java多线程机制

J a v a第七单元练习题 J a v a多线程机制 The latest revision on November 22, 2020

7Java多线程机制 7.1单项选择题 1. 线程调用了sleep()方法后,该线程将进入()状态。 A. 可运行状态 B. 运行状态 C. 阻塞状态 D. 终止状态 2. 关于java线程,下面说法错误的是() A. 线程是以CPU为主体的行为 B. java利用线程使整个系统成为异步 C. 创建线程的方法有两种:实现Runnable接口和继承Thread类 D. 新线程一旦被创建,它将自动开始运行 3. 在java中的线程模型包含() A. 一个虚拟处理器 B. CPU执行的代码 C. 代码操作的数据 D. 以上都是 4.在java语言中,临界区可以是一个语句块,或者是一个方法,并用()关键字标识。 A. synchronized B. include C. import D. Thread 5. 线程控制方法中,yield()的作用是() A. 返回当前线程的引用 B. 使比其低的优先级线程执行 C. 强行终止线程 D. 只让给同优先级线程运行 6. 线程同步中,对象的锁在()情况下持有线程返回 A. 当synchronized()语句块执行完后 B. 当在synchronized()语句块执行中出现例外(exception)时 C. 当持有锁的线程调用该对象的wait()方法时 D. 以上都是 7. 在以下()情况下,线程就进入可运行状态 A. 线程调用了sleep()方法时 B. 线程调用了join()方法时 C. 线程调用了yield()方法时 D. 以上都是 8. java用()机制实现了进程之间的异步执行

java线程学习总结

java线程学习总结1(java thread培训总结1) 1.线程中一些基本术语和概念 (2) 1.1线程的几个状态 (2) 1.2 Daemon线程 (2) 1.3锁的定义 (2) 1.4死锁 (2) 1.5.Java对象关于锁的几个方法 (3) 1.6锁对象(实例方法的锁) (3) 1.7类锁 (4) 1.8.线程安全方法与线程不安全方法 (4) 1.9类锁和实例锁混合使用 (4) 1.10锁的粒度问题 (4) 1.11.读写锁 (5) 1.12 volatile (5) 2.线程之间的通讯 (5) 2.1屏障 (6) 2.2.锁工具类 (6) 2.3.条件变量 (6) 3. Java线程调度 (7) 3.1 Java优先级 (7) 3.2. 绿色线程 (7) 3.3 本地线程 (7) 3.4 Windows本地线程 (7) 3.5线程优先级倒置与继承 (8) 3.6循环调度 (8) 4.线程池 (8) 5工作队列 (9) 6.参考资料 (10)

1.线程中一些基本术语和概念 1.1线程的几个状态 初始化状态 就绪状态 运行状态 阻塞状态 终止状态 1.2 Daemon线程 Daemon线程区别一般线程之处是:主程序一旦结束,Daemon线程就会结束。 1.3锁的定义 为了协调多个并发运行的线程使用共享资源才引入了锁的概念。 1.4死锁 任何多线程应用程序都有死锁风险。当一组线程中的每一个都在等待一个只 有该组中另一个线程才能引起的事件时,我们就说这组线程死锁了。换一个说法就是一组线程中的每一个成员都在等待别的成员占有的资源时候,就可以说这组线程进入了死锁。死锁的最简单情形是:线程 A 持有对象X 的独占锁,并且在等待对象Y 的锁,而线程 B 持有对象Y 的独占锁,却在等待对象X 的锁。除非有某种方法来打破对锁的等待(Java 锁定不支持这种方法),否则死锁的线程将永远等下去。

精选大厂java多线程面试题50题

Java多线程50题 1)什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒。 2)线程和进程有什么区别? 线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。更多详细信息请点击这里。 3)如何在Java中实现线程? https://www.wendangku.net/doc/2f17674335.html,ng.Thread类的实例就是一个线程但是它需要调用https://www.wendangku.net/doc/2f17674335.html,ng.Runnable接口来执行,由于线程类本身就是调用的 Runnable接口所以你可以继承https://www.wendangku.net/doc/2f17674335.html,ng.Thread类或者直接调用Runnable接口来重写run()方法实现线程。 4)Thread类中的start()和run()方法有什么区别? 这个问题经常被问到,但还是能从此区分出面试者对Java线程模型的理解程度。start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当你

调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。 5)Java中Runnable和Callable有什么不同? Runnable和Callable都代表那些要在不同的线程中执行的任务。Runnable从JDK1.0开始就有了,Callable是在JDK1.5增加的。它们的主要区别是Callable的call()方法可以返回值和抛出异常,而Runnable的run()方法没有这些功能。Callable可以返回装载有计算结果的Future对象。 6)Java内存模型是什么? Java内存模型规定和指引Java程序在不同的内存架构、CPU 和操作系统间有确定性地行为。它在多线程的情况下尤其重要。 Java内存模型对一个线程所做的变动能被其它线程可见提供了保证,它们之间是先行发生关系。 ●线程内的代码能够按先后顺序执行,这被称为程序次序 规则。 ●对于同一个锁,一个解锁操作一定要发生在时间上后发 生的另一个锁定操作之前,也叫做管程锁定规则。 ●前一个对Volatile的写操作在后一个volatile的读操作之 前,也叫volatile变量规则。 ●一个线程内的任何操作必需在这个线程的start()调用之 后,也叫作线程启动规则。 ●一个线程的所有操作都会在线程终止之前,线程终止规

多线程总结

最近想将java基础的一些东西都整理整理,写下来,这是对知识的总结,也是一种乐趣。已经拟好了提纲,大概分为这几个主题: java线程安全,java垃圾收集,java并发包详细介绍,java profile和jvm性能调优。慢慢写吧。本人jameswxx原创文章,转载请注明出处,我费了很多心血,多谢了。关于java线程安全,网上有很多资料,我只想从自己的角度总结对这方面的考虑,有时候写东西是很痛苦的,知道一些东西,想用文字说清楚,却不是那么容易。我认为要认识 java线程安全,必须了解两个主要的点:java的内存模型,java的线程同步机制。特别是内存模型,java的线程同步机制很大程度上都是基于内存模型而设定的。从暂时写得比较仓促,后面会慢慢补充完善。 浅谈java内存模型 不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的。java的多线程并发问题最终都会反映在java的内存模型上,所谓线程安全无非要控制多个线程对某个资源的有序访问或修改。java的内存模型,要解决两个主要的问题:可见性和有序性。我们都知道计算机有高速缓存的存在,处理器并不是每次处理数据都是取内存的。JVM定义了自己的内存模型,屏蔽了底层平台内存管理细节,对于java开发人员,要解决的是在jvm内存模型的基础上,如何解决多线程的可见性和有序性。 那么,何谓可见性?多个线程之间是不能互相传递数据通信的,它们之间的沟通只能通过共享变量来进行。Java内存模型(JMM)规定了jvm有主内存,主内存是多个线程共享的。当new一个对象的时候,也是被分配在主内存中,每个线程都有自己的工作内存,工作内存存储了主存的某些对象的副本,当然线程的工作内存大小是有限制的。当线程操作某个对象时,执行顺序如下: (1) 从主存复制变量到当前工作内存 (read and load) (2) 执行代码,改变共享变量值 (use and assign) (3) 用工作内存数据刷新主存相关内容 (store and write) JVM规范定义了线程对主存的操作指令:read,load,use,assign,store,write。当一个共享便变量在多个线程的工作内存中都有副本时,如果一个线程修改了这个共享变量,那么其他线程应该能够看到这个被修改后的值,这就是多线程的可见性问题。 那么,什么是有序性呢?线程在引用变量时不能直接从主内存中引用,如果线程工作内存中没有该变量,则会从主内存中拷贝一个副本到工作内存中,这个过程为read-load,完成后线程会引用该副本。当同一线程再度引用该字段时,有可能重新从主存中获取变量副本(read-load-use),也有可能直接引用原来的副本 (use),也就是说 read,load,use顺序可以由JVM实现系统决定。 线程不能直接为主存中中字段赋值,它会将值指定给工作内存中的变量副本(assign),完成后这个变量副本会同步到主存储区(store- write),至于何时同步过去,根据JVM实现系统决定.有该字段,则会从主内存中将该字段赋值到工作内存中,这个过程为read-load,完成后线程会引用该变量副本,当同一线程多次重复对字段赋值时,比如: for(int i=0;i<10;i++) a++; 线程有可能只对工作内存中的副本进行赋值,只到最后一次赋值后才同步到主存储区,所以assign,store,weite顺序可以由JVM实现系统决定。假设有一个共享变量x,线程a执行x=x+1。从上面的描述中可以知道x=x+1并不是一个原子操作,它的执行过程如下:

2019最新Java面试题,常见面试题及答案汇总

ava最新常见面试题+ 答案汇总 1、面试题模块汇总 面试题包括以下十九个模块:Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySql、Redis、JVM 。如下图所示: 可能对于初学者不需要后面的框架和JVM 模块的知识,读者朋友们可根据自己的情况,选择对应的模块进行阅读。 适宜阅读人群 需要面试的初/中/高级java 程序员 想要查漏补缺的人 想要不断完善和扩充自己java 技术栈的人 java 面试官 具体面试题 下面一起来看208 道面试题,具体的内容。 一、Java 基础 1.JDK 和JRE 有什么区别? 2.== 和equals 的区别是什么? 3.两个对象的hashCode()相同,则equals()也一定为true,对吗? 4.final 在java 中有什么作用? 5.java 中的Math.round(-1.5) 等于多少? 6.String 属于基础的数据类型吗? 7.java 中操作字符串都有哪些类?它们之间有什么区别? 8.String str="i"与String str=new String(“i”)一样吗? 9.如何将字符串反转? 10.String 类的常用方法都有那些? 11.抽象类必须要有抽象方法吗? 12.普通类和抽象类有哪些区别? 13.抽象类能使用final 修饰吗?

14.接口和抽象类有什么区别? 15.java 中IO 流分为几种? 16.BIO、NIO、AIO 有什么区别? 17.Files的常用方法都有哪些? 二、容器 18.java 容器都有哪些? 19.Collection 和Collections 有什么区别? 20.List、Set、Map 之间的区别是什么? 21.HashMap 和Hashtable 有什么区别? 22.如何决定使用HashMap 还是TreeMap? 23.说一下HashMap 的实现原理? 24.说一下HashSet 的实现原理? 25.ArrayList 和LinkedList 的区别是什么? 26.如何实现数组和List 之间的转换? 27.ArrayList 和Vector 的区别是什么? 28.Array 和ArrayList 有何区别? 29.在Queue 中poll()和remove()有什么区别? 30.哪些集合类是线程安全的? 31.迭代器Iterator 是什么? 32.Iterator 怎么使用?有什么特点? 33.Iterator 和ListIterator 有什么区别? 34.怎么确保一个集合不能被修改?

java学习整体总结

CoreJava部分 1 简述下java基本数据类型及所占位数,java基本数据类型:4类8种 整数类型:byte(1byte),short(2byte),int(4byte),long(8byte) 浮点类型:float(4byte),double(8byte) 字符类型:char(2byte) 逻辑类型:boolean(false/true 1byte) 2 说出5个启动时异常 RunTimeException ------NullPointerException ------ArrayIndexOutOfBoundsException ------ClassCastException ------NumberFormatException 3 HashMap 和HashTable的区别: 1HashMap 允许空键值对,HashTable不允许 2HashMap不是线程安全的,HashTable是 3HashMap直接实现Map接口,HashTable继承Dictionary类 4. ArrayList,Vector,LinkedList存储性能和区别 它们都实现了List接口 ArrayList和Vector都是基于数组实现的 LinkedList基于双向循环链表(查找效率低,添加删除容易) ArrayList不是线程安全的而Vector是线程安全的,所有速度上 ArrayList高于Vector 5. Collection和Collections的区别 Collection是集合类的上级接口,继承与他的接口主要有Set和List Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全等操作。 6 List、Map、Set三个接口,存取元素时,各有什么特点? List以特定次序来持有元素,可有重复元素。 Set 无法持有重复元素,内部排序 Map保存key-value值,value可多值。 7 final,finally,finalize的区别 Final用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承 Finally 是异常处理语句结构的一部分,表示总是执行 Finalize 是Object类的一个方法,在垃圾收集时的其他资源回收,例如关闭文件等。 8 Overload和Override的区别。Overload的方法是否可以改变返回值的

15个Java多线程面试题及答案

15个Java多线程面试题及答案 1)现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行? 这个线程问题通常会在第一轮或电话面试阶段被问到,目的是检测你对”join”方法是否熟悉。这个多线程问题比较简单,可以用join方法实现。 2)在Java中Lock接口比synchronized块的优势是什么?你需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,以此来保持它的完整性,你会怎样去实现它? lock接口在多线程和并发编程中最大的优势是它们为读和写分别提 供了锁,它能满足你写像ConcurrentHashMap这样的高性能数据结构和有条件的阻塞。Java线程面试的问题越来越会根据面试者的回答来提问。芯学苑老师强烈建议在你在面试之前认真读一下Locks,因为当前其大量用于构建电子交易终统的客户端缓存和交易连接空间。 3)在java中wait和sleep方法的不同?

通常会在电话面试中经常被问到的Java线程面试问题。最大的不同是在等待时wait会释放锁,而sleep一直持有锁。Wait通常被用于线程间交互,sleep通常被用于暂停执行。 4)用Java实现阻塞队列。 这是一个相对艰难的多线程面试问题,它能达到很多的目的。第一,它可以检测侯选者是否能实际的用Java线程写程序;第二,可以检测侯选者对并发场景的理解,并且你可以根据这个问很多问题。如果他用wait()和notify()方法来实现阻塞队列,你可以要求他用最新的Java 5中的并发类来再写一次。 5)用Java写代码来解决生产者——消费者问题。 与上面的问题很类似,但这个问题更经典,有些时候面试都会问下面的问题。在Java中怎么解决生产者——消费者问题,当然有很多解决方法,我已经分享了一种用阻塞队列实现的方法。有些时候他们甚至会问怎么实现哲学家进餐问题。 6)用Java编程一个会导致死锁的程序,你将怎么解决?

java并发编程艺术总结.

1、并发编程的挑战 上下文切换:CPU通过时间片分配算法来循环执行任务,在切换任务的过程中,会保存上一个任务的状态,以便在下次切换回这个任务时,可以再加载这个任务的状态。 减少上下文切换的方法:无锁并发编程、CAS算法、使用最少线程和使用协程 2、Java并发机制的底层实现原理 Java代码编译后java字节码然后加载到JVM然后转化为CUP执行的汇编,java的并发依赖于JVM的实现与CPU的指令。 1. Volatile的应用 可见性:当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。 后面还是详细介绍volatile关键字 2. synchronized的实现原理与应用 1) synchronized简介 synchronized在JVM中实现,JVM基于进入与退出Monitor对象来实现方法同步与代码块同步,在同步代码块前后分别形成monitorenter和monitorexit这两个字节码。synchronized的锁存放在java对象头里,在对象头里有关于锁的信息:轻量级锁,重量级锁,偏向锁。(对象头里还包括:GC标记、分代年龄、线程ID、HashCode等。) 2) 锁的介绍 级别从低到高:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态,锁能升级不能降级,目的是提高获取锁和释放锁的效率。 偏向锁: 在大多数情况下,锁不仅不存在多线程竞争,而且总是由同一个线程多次获得。

为了让线程获得锁的代价更低而引入了偏向锁。 当一个线程访问同步块并获取锁(对象)时,会在对象头里记录偏向锁的线程ID。以后该线程进入与退出同步块时不需要进行CAS操作来加锁和解锁。如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会尝试消除它身上的偏向锁,将锁恢复到标准的轻量级锁。 轻量级锁: 线程通过CAS来获取锁(线程栈帧中有存储锁记录的空间,将Mask Word复制到锁记录中,然后尝试使用CAS将对象头中的Mask Word替换成指向锁记录的指针),如果成功,就获取锁,失败就尝试自旋来获取锁。 重量级锁: 为了避免在轻量级中无用的自旋(比如获取到锁的线程被阻塞住了),JVM可以将锁升级成重量级。当锁处于这个状态时,其他线程试图获取锁时,都会被阻塞住,当持有锁的线程释放锁之后会唤醒这些线程。 锁优点缺点使用场景 偏向锁加锁与解锁不需要 额外的消耗。线程存在竞争时, 会带来额外的锁撤 销的消耗 适用于只有一个 线程访问同步块 轻量级锁竞争的线程不会阻 塞,提高了程序的 响应速度始终得不到锁竞争 的线程,自旋消耗 CPU 追求响应时间, 同步块执行速度 非常快 重量级锁线程竞争不使用自 旋,不会消耗CPU 线程阻塞,响应时 间缓慢 追求吞吐量,同 步块执行时间较 长 3. 原子操作的实现原理 原子:不能被中断的一个或一系列操作。 在java中可以通过锁和循环CAS的方式来实现原子操作。 1) 使用循环CAS实现原子操作 利用处理器提供的CAS指令来实现,自旋CAS现在的基本思路就是循环进

Java第七单元练习题Java多线程机制(20210109223217)

7 Java 多线程机制 7.1 单项选择题 1. 线程调用了sleep ()方法后,该线程将进入( )状态。 A. 可运行状态 B. 运行状态 C. 阻塞状态 D. 终止状态 2. 关于java 线程,下面说法错误的是() A. 线程是以CPU为主体的行为 B. java 利用线程使整个系统成为异步 C. 创建线程的方法有两种:实现Runnable 接口和继承Thread 类 D. 新线程一旦被创建,它将自动开始运行 3. 在java 中的线程模型包含() A. 一个虚拟处理器 B. CPU执行的代码 C. 代码操作的数据 D. 以上都是 4. 在java 语言中,临界区可以是一个语句块,或者是一个方法,并用()关键字标识。 A. synchronized B. include C. import D. Thread 5. 线程控制方法中,yield()的作用是() A. 返回当前线程的引用 B. 使比其低的优先级线程执行 C. 强行终止线程 D. 只让给同优先级线程运行 6. 线程同步中,对象的锁在()情况下持有线程返回 A. 当synchronized()语句块执行完后 B. 当在synchronized()语句块执行中出现例外( exception )时 C. 当持有锁的线程调用该对象的wait()方法时 D. 以上都是 7. 在以下()情况下,线程就进入可运行状态 A. 线程调用了sleep()方法时 B. 线程调用了join()方法时 C. 线程调用了yield()方法时 D. 以上都是 8. java 用()机制实现了进程之间的异步执行 A. 监视器 B. 虚拟机

多线程与并发面试题

多线程与并发面试题

JAVA多线程和并发基础面试问答 原文链接译文连接作者:Pankaj 译者:郑旭东校对:方腾飞 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一。在这里,从面试的角度列出了大部分重要的问题,可是你依然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题。(校对注:非常赞同这个观点) Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它能够被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一个包含了不同的类和程序的单一进程。线程能够被称为轻量级进程。线程需要较少的资源来创立和驻留在进程中,而且能够共享进程中的资源。 2. 多线程编程的好处是什么?

在多线程程序中,多个线程被并发的执行以提高程序的效率,CPU不会因为某个线程需要等待资源而进入空闲状态。多个线程共享堆内存(heap memory),因此创立多个线程去执行一些任务会比创立多个进程更好。举个例子,Servlets比CGI更好,是因为Servlets支持多线程而CGI不支持。 3. 用户线程和守护线程有什么区别? 当我们在Java程序中创立一个线程,它就被称为用户线程。一个守护线程是在后台执行而且不会阻止JVM终止的线程。当没有用户线程在运行的时候,JVM关闭程序而且退出。一个守护线程创立的子线程依然是守护线程。 4. 我们如何创立一个线程? 有两种创立线程的方法:一是实现Runnable接口,然后将它传递给Thread的构造函数,创立一个Thread对象;二是直接继承Thread类。若想了解更多能够阅读这篇关于如何在Java中创立线程的文章。 5. 有哪些不同的线程生命周期?

相关文档
相关文档 最新文档